package com.wondertek.onvif.service;

import cn.hutool.core.util.StrUtil;
import com.wondertek.onvif.dto.AddDeviceByIpRequest;
import com.wondertek.onvif.dto.BatchAddDevicesRequest;
import com.wondertek.onvif.dto.BatchAddDevicesResponse;
import com.wondertek.onvif.entity.OnvifChannel;
import com.wondertek.onvif.entity.OnvifDevice;
import com.wondertek.onvif.repository.OnvifChannelRepository;
import com.wondertek.onvif.repository.OnvifDeviceRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.http.ResponseEntity;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.Map;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.stream.Collectors;
import java.util.regex.Pattern;
import java.util.regex.Matcher;

/**
 * ONVIF设备管理服务
 * 
 * @author wondertek
 * @version 1.0.0
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class OnvifDeviceService {

    private static final Logger log = LoggerFactory.getLogger(OnvifDeviceService.class);
    
    private final OnvifDeviceRepository deviceRepository;
    private final OnvifChannelRepository channelRepository;
    private final OnvifClientService onvifClientService;
    
    @Value("${gb28181.administrative-code:34010000}")
    private String administrativeCode;
    
    @Value("${gb28181.industry-code:11}")
    private String industryCode;
    
    @Value("${gb28181.device-type-code:001}")
    private String deviceTypeCode;

    /**
     * Get all devices
     * 
     * @return Device list
     */
    public List<OnvifDevice> getAllDevices() {
        return deviceRepository.findAll();
    }

    /**
     * Find device by IP address and port
     * 
     * @param ipAddress IP address
     * @param port Port
     * @return Device (if exists)
     */
    public Optional<OnvifDevice> findByIpAddressAndPort(String ipAddress, Integer port) {
        return deviceRepository.findByIpAddressAndPort(ipAddress, port);
    }

    /**
     * Get devices with pagination
     * 
     * @param pageable Pagination parameters
     * @return Device pagination data
     */
    public Page<OnvifDevice> getDevices(Pageable pageable) {
        return deviceRepository.findAll(pageable);
    }

    /**
     * Get devices with pagination by multiple conditions
     * 
     * @param pageable Pagination parameters
     * @param keyword Search keyword (device name)
     * @param status Device status
     * @param manufacturer Manufacturer
     * @param enabled Whether enabled
     * @return Device pagination data
     */
    public Page<OnvifDevice> getDevicesWithFilters(Pageable pageable, String keyword, 
                                                   String status, String manufacturer, Boolean enabled) {
        log.info("Query device list - parameters: keyword={}, status={}, manufacturer={}, enabled={}, page={}, size={}", 
                keyword, status, manufacturer, enabled, pageable.getPageNumber(), pageable.getPageSize());
        
        // Get all devices
        List<OnvifDevice> allDevices = deviceRepository.findAll();
        log.info("Total device count in database: {}", allDevices.size());
        
        // Apply filter conditions
        List<OnvifDevice> filteredDevices = allDevices.stream()
            .filter(device -> {
                // Keyword filter (device name)
                if (StrUtil.isNotEmpty(keyword)) {
                    boolean nameMatch = device.getName().toLowerCase().contains(keyword.toLowerCase());
                    if (!nameMatch) {
                        log.debug("设备 {} 不匹配关键字 {}", device.getName(), keyword);
                        return false;
                    }
                }
                
                // 状态过滤
                if (StrUtil.isNotEmpty(status)) {
                    try {
                        OnvifDevice.DeviceStatus deviceStatus = OnvifDevice.DeviceStatus.valueOf(status.toUpperCase());
                        if (device.getStatus() != deviceStatus) {
                            log.debug("设备 {} 状态 {} 不匹配过滤条件 {}", device.getName(), device.getStatus(), status);
                            return false;
                        }
                    } catch (IllegalArgumentException e) {
                        log.warn("无效的设备状态值: {}", status);
                        // 忽略无效的状态值
                    }
                }
                
                // 制造商过滤
                if (StrUtil.isNotEmpty(manufacturer)) {
                    String deviceManufacturer = device.getManufacturer();
                    if (deviceManufacturer == null || !manufacturer.equalsIgnoreCase(deviceManufacturer)) {
                        log.debug("设备 {} 制造商 {} 不匹配过滤条件 {}", device.getName(), deviceManufacturer, manufacturer);
                        return false;
                    }
                }
                
                // 启用状态过滤
                if (enabled != null) {
                    if (!enabled.equals(device.getEnabled())) {
                        log.debug("设备 {} 启用状态 {} 不匹配过滤条件 {}", device.getName(), device.getEnabled(), enabled);
                        return false;
                    }
                }
                
                log.debug("设备 {} 通过所有过滤条件", device.getName());
                return true;
            })
            .collect(java.util.stream.Collectors.toList());
        
        log.info("过滤后设备数量: {}", filteredDevices.size());
        
        // 应用排序
        if (pageable.getSort().isSorted()) {
            filteredDevices.sort((d1, d2) -> {
                for (org.springframework.data.domain.Sort.Order order : pageable.getSort()) {
                    String property = order.getProperty();
                    int comparison = 0;
                    
                    switch (property) {
                        case "id":
                            comparison = d1.getId().compareTo(d2.getId());
                            break;
                        case "name":
                            comparison = d1.getName().compareTo(d2.getName());
                            break;
                        case "ipAddress":
                            comparison = d1.getIpAddress().compareTo(d2.getIpAddress());
                            break;
                        case "manufacturer":
                            String m1 = d1.getManufacturer() != null ? d1.getManufacturer() : "";
                            String m2 = d2.getManufacturer() != null ? d2.getManufacturer() : "";
                            comparison = m1.compareTo(m2);
                            break;
                        case "status":
                            comparison = d1.getStatus().compareTo(d2.getStatus());
                            break;
                        case "createTime":
                        case "createdAt":
                            comparison = d1.getCreateTime().compareTo(d2.getCreateTime());
                            break;
                        case "updateTime":
                        case "updatedAt":
                            comparison = d1.getUpdateTime().compareTo(d2.getUpdateTime());
                            break;
                        default:
                            comparison = 0;
                    }
                    
                    if (comparison != 0) {
                        return order.isAscending() ? comparison : -comparison;
                    }
                }
                return 0;
            });
        }
        
        // 应用分页
        int start = (int) pageable.getOffset();
        int end = Math.min(start + pageable.getPageSize(), filteredDevices.size());
        
        log.info("分页计算 - start: {}, end: {}, filteredDevices.size(): {}, pageNumber: {}, pageSize: {}", 
                start, end, filteredDevices.size(), pageable.getPageNumber(), pageable.getPageSize());
        
        List<OnvifDevice> pageContent = start < filteredDevices.size() ? 
            filteredDevices.subList(start, end) : new java.util.ArrayList<>();
        
        log.info("最终返回的设备数量: {}", pageContent.size());
        
        return new org.springframework.data.domain.PageImpl<>(
            pageContent, pageable, filteredDevices.size());
    }

    /**
     * 根据ID获取设备
     * 
     * @param id 设备ID
     * @return 设备信息
     */
    public Optional<OnvifDevice> getDeviceById(Long id) {
        return deviceRepository.findById(id);
    }

    /**
     * 根据设备ID获取设备
     * 
     * @param deviceId Device ID
     * @return 设备信息
     */
    public Optional<OnvifDevice> getDeviceByDeviceId(String deviceId) {
        return deviceRepository.findByDeviceId(deviceId);
    }

    /**
     * 根据IP地址获取设备
     * 
     * @param ipAddress IP地址
     * @return 设备信息
     */
    public Optional<OnvifDevice> getDeviceByIpAddress(String ipAddress) {
        return deviceRepository.findByIpAddress(ipAddress);
    }

    /**
     * 获取启用的设备列表
     * 
     * @return 启用的设备列表
     */
    public List<OnvifDevice> getEnabledDevices() {
        return deviceRepository.findByEnabledTrue();
    }

    /**
     * 根据状态获取设备列表
     * 
     * @param status 设备状态
     * @return 设备列表
     */
    public List<OnvifDevice> getDevicesByStatus(OnvifDevice.DeviceStatus status) {
        return deviceRepository.findByStatus(status);
    }

    /**
     * 搜索设备
     * 
     * @param keyword 关键字
     * @return 设备列表
     */
    public List<OnvifDevice> searchDevices(String keyword) {
        if (StrUtil.isEmpty(keyword)) {
            return getAllDevices();
        }
        return deviceRepository.findByNameContainingIgnoreCase(keyword);
    }

    /**
     * 添加设备
     * 
     * @param device 设备信息
     * @return 保存的设备
     */
    @Transactional
    public OnvifDevice addDevice(OnvifDevice device) {
        log.info("添加ONVIF设备: {} - {}:{}", device.getName(), device.getIpAddress(), device.getPort());
        
        // 检查IP地址和端口是否已存在
        Optional<OnvifDevice> existingDevice = deviceRepository.findByIpAddressAndPort(
            device.getIpAddress(), device.getPort());
        if (existingDevice.isPresent()) {
            throw new RuntimeException("设备已存在: " + device.getIpAddress() + ":" + device.getPort());
        }
        
        // 设置默认值
        if (device.getPort() == null) {
            device.setPort(80);
        }
        if (device.getStatus() == null) {
            device.setStatus(OnvifDevice.DeviceStatus.OFFLINE);
        }
        if (device.getEnabled() == null) {
            device.setEnabled(true);
        }
        
        // 生成唯一的设备ID
        if (StrUtil.isEmpty(device.getDeviceId())) {
            device.setDeviceId(generateDeviceId());
        }
        
        // 保存设备
        OnvifDevice savedDevice = deviceRepository.save(device);
        
        // 异步连接设备并获取信息
        connectAndUpdateDeviceInfo(savedDevice.getDeviceId());
        
        return savedDevice;
    }

    /**
     * 根据IP地址、用户名和密码添加设备
     * 
     * @param request 添加设备请求
     * @return 添加的设备
     */
    @Transactional
    public OnvifDevice addDeviceByIp(AddDeviceByIpRequest request) {
        log.info("根据IP添加ONVIF设备: {}:{}", request.getIpAddress(), request.getPort());
        
        // 检查IP地址和端口是否已存在
        Optional<OnvifDevice> existingDevice = deviceRepository.findByIpAddressAndPort(
            request.getIpAddress(), request.getPort());
        if (existingDevice.isPresent()) {
            OnvifDevice device = existingDevice.get();
            // 更新现有设备的认证信息
            device.setUsername(request.getUsername());
            device.setPassword(request.getPassword());
            if (request.getCustomName() != null && !request.getCustomName().trim().isEmpty()) {
                device.setName(request.getCustomName());
            }
            // updateTime字段会通过@UpdateTimestamp自动更新，无需手动设置
            
            OnvifDevice updatedDevice = deviceRepository.save(device);
            log.info("设备已存在，已更新设备信息: {}:{}", request.getIpAddress(), request.getPort());
            return updatedDevice;
        }
        
        // 创建临时设备对象用于测试连接
        OnvifDevice testDevice = new OnvifDevice();
        testDevice.setIpAddress(request.getIpAddress());
        testDevice.setPort(request.getPort());
        testDevice.setUsername(request.getUsername());
        testDevice.setPassword(request.getPassword());
        
        // 测试设备连接
        boolean connectionTest = onvifClientService.testConnection(testDevice);
        if (!connectionTest) {
            throw new RuntimeException("无法连接到设备，请检查IP地址、端口、用户名和密码是否正确");
        }
        
        // 尝试获取设备信息
        OnvifClientService.DeviceInfo deviceInfo = onvifClientService.getDeviceInfo(testDevice);
        
        // 如果有认证信息但获取失败，或者没有认证信息，尝试无认证方式获取设备信息
        if (deviceInfo == null || 
            (StrUtil.isEmpty(deviceInfo.getManufacturer()) && StrUtil.isEmpty(deviceInfo.getModel()))) {
            log.info("尝试无认证方式获取设备信息: {}:{}", request.getIpAddress(), request.getPort());
            OnvifClientService.DeviceInfo noAuthDeviceInfo = onvifClientService.getDeviceInfoWithoutAuth(testDevice);
            if (noAuthDeviceInfo != null && 
                (StrUtil.isNotEmpty(noAuthDeviceInfo.getManufacturer()) || StrUtil.isNotEmpty(noAuthDeviceInfo.getModel()))) {
                deviceInfo = noAuthDeviceInfo;
                log.info("无认证方式成功获取到设备信息");
            }
        }
        
        // 创建设备对象
        OnvifDevice device = new OnvifDevice();
        device.setIpAddress(request.getIpAddress());
        device.setPort(request.getPort());
        device.setUsername(request.getUsername());
        device.setPassword(request.getPassword());
        
        // 设置服务URL
        device.setServiceUrl(String.format("http://%s:%d/onvif/device_service", 
            request.getIpAddress(), request.getPort()));
        
        // 设置设备名称
        if (StrUtil.isNotBlank(request.getCustomName())) {
            device.setName(request.getCustomName());
        } else if (deviceInfo != null && StrUtil.isNotBlank(deviceInfo.getModel())) {
            device.setName(deviceInfo.getModel() + "_" + request.getIpAddress());
        } else {
            device.setName("ONVIF设备_" + request.getIpAddress());
        }
        
        // 设置设备信息（如果获取到）
        if (deviceInfo != null) {
            device.setManufacturer(StrUtil.isNotBlank(deviceInfo.getManufacturer()) ? 
                deviceInfo.getManufacturer() : "Unknown");
            device.setModel(StrUtil.isNotBlank(deviceInfo.getModel()) ? 
                deviceInfo.getModel() : "Unknown Model");
            device.setFirmwareVersion(StrUtil.isNotBlank(deviceInfo.getFirmwareVersion()) ? 
                deviceInfo.getFirmwareVersion() : "Unknown");
            device.setSerialNumber(StrUtil.isNotBlank(deviceInfo.getSerialNumber()) ? 
                deviceInfo.getSerialNumber() : "Unknown");
            device.setHardwareId(StrUtil.isNotBlank(deviceInfo.getHardwareId()) ? 
                deviceInfo.getHardwareId() : "Unknown");
            
            // 设置新增的设备信息字段
            if (StrUtil.isNotBlank(deviceInfo.getDeviceType())) {
                device.setDeviceType(deviceInfo.getDeviceType());
            }
            if (StrUtil.isNotBlank(deviceInfo.getLocation())) {
                device.setLocation(deviceInfo.getLocation());
            }
            if (StrUtil.isNotBlank(deviceInfo.getMacAddress())) {
                device.setMacAddress(deviceInfo.getMacAddress());
            }
            
            // 如果没有自定义名称且获取到了设备名称，使用设备名称
            if (StrUtil.isBlank(request.getCustomName()) && StrUtil.isNotBlank(deviceInfo.getDeviceName())) {
                device.setName(deviceInfo.getDeviceName());
            }
        } else {
            // 如果无法获取设备信息，设置默认值
            device.setManufacturer("Unknown");
            device.setModel("Unknown Model");
            device.setFirmwareVersion("Unknown");
            device.setSerialNumber("Unknown");
            device.setHardwareId("Unknown");
        }
        
        // 设置描述
        if (StrUtil.isNotBlank(request.getDescription())) {
            device.setDescription(request.getDescription());
        } else {
            device.setDescription("手动添加的设备");
        }
        
        // 设置默认值
        device.setStatus(OnvifDevice.DeviceStatus.ONLINE); // 连接测试成功，设为在线
        device.setEnabled(true);
        
        // 生成唯一的设备ID
        device.setDeviceId(generateDeviceId());
        
        // 保存设备
        OnvifDevice savedDevice = deviceRepository.save(device);
        
        // 立即尝试获取设备信息并更新
        try {
            // 测试连接
            boolean connected = onvifClientService.testConnection(savedDevice);
            if (connected) {
                // 获取设备信息
                deviceInfo = onvifClientService.getDeviceInfo(savedDevice);
                
                // 如果获取失败或信息不完整，尝试无认证方式
                if (deviceInfo == null || 
                    (StrUtil.isEmpty(deviceInfo.getManufacturer()) && StrUtil.isEmpty(deviceInfo.getModel()))) {
                    log.info("尝试无认证方式重新获取设备信息: {}:{}", savedDevice.getIpAddress(), savedDevice.getPort());
                    OnvifClientService.DeviceInfo noAuthDeviceInfo = onvifClientService.getDeviceInfoWithoutAuth(savedDevice);
                    if (noAuthDeviceInfo != null && 
                        (StrUtil.isNotEmpty(noAuthDeviceInfo.getManufacturer()) || StrUtil.isNotEmpty(noAuthDeviceInfo.getModel()))) {
                        deviceInfo = noAuthDeviceInfo;
                        log.info("无认证方式成功重新获取到设备信息");
                    }
                }
                
                if (deviceInfo != null) {
                    // 更新设备信息
                    if (StrUtil.isNotEmpty(deviceInfo.getManufacturer())) {
                        savedDevice.setManufacturer(deviceInfo.getManufacturer());
                    }
                    if (StrUtil.isNotEmpty(deviceInfo.getModel())) {
                        savedDevice.setModel(deviceInfo.getModel());
                    }
                    if (StrUtil.isNotEmpty(deviceInfo.getFirmwareVersion())) {
                        savedDevice.setFirmwareVersion(deviceInfo.getFirmwareVersion());
                    }
                    if (StrUtil.isNotEmpty(deviceInfo.getSerialNumber())) {
                        savedDevice.setSerialNumber(deviceInfo.getSerialNumber());
                    }
                    if (StrUtil.isNotEmpty(deviceInfo.getHardwareId())) {
                        savedDevice.setHardwareId(deviceInfo.getHardwareId());
                    }
                    
                    // 更新新增的设备信息字段
                    if (StrUtil.isNotEmpty(deviceInfo.getDeviceType())) {
                        savedDevice.setDeviceType(deviceInfo.getDeviceType());
                    }
                    if (StrUtil.isNotEmpty(deviceInfo.getLocation())) {
                        savedDevice.setLocation(deviceInfo.getLocation());
                    }
                    if (StrUtil.isNotEmpty(deviceInfo.getMacAddress())) {
                        savedDevice.setMacAddress(deviceInfo.getMacAddress());
                    }
                    if (StrUtil.isNotEmpty(deviceInfo.getDeviceName()) && 
                        StrUtil.isBlank(request.getCustomName())) {
                        savedDevice.setName(deviceInfo.getDeviceName());
                    }
                    
                    // 保存更新后的设备信息
                    savedDevice = deviceRepository.save(savedDevice);
                    
                    // 设置设备状态为在线
                    savedDevice.setStatus(OnvifDevice.DeviceStatus.ONLINE);
                    savedDevice.setLastOnlineTime(LocalDateTime.now());
                    savedDevice = deviceRepository.save(savedDevice);
                    
                    log.info("设备信息获取成功: {} - 制造商: {}, 型号: {}", 
                        savedDevice.getName(), savedDevice.getManufacturer(), savedDevice.getModel());
                } else {
                    log.warn("无法获取设备 {} 的详细信息，但连接正常", savedDevice.getName());
                    // 设置设备状态为在线
                    savedDevice.setStatus(OnvifDevice.DeviceStatus.ONLINE);
                    savedDevice.setLastOnlineTime(LocalDateTime.now());
                    savedDevice = deviceRepository.save(savedDevice);
                }
            } else {
                log.warn("设备 {} 连接失败，设置为离线状态", savedDevice.getName());
                savedDevice.setStatus(OnvifDevice.DeviceStatus.OFFLINE);
                savedDevice = deviceRepository.save(savedDevice);
            }
        } catch (Exception e) {
            log.error("获取设备信息时发生异常: {}", e.getMessage(), e);
            // 即使获取信息失败，也保持设备为离线状态
            savedDevice.setStatus(OnvifDevice.DeviceStatus.OFFLINE);
            savedDevice = deviceRepository.save(savedDevice);
        }
        
        // 异步连接设备并更新通道信息
        connectAndUpdateDeviceInfo(savedDevice.getDeviceId());
        
        log.info("设备添加成功: {} - {}:{}", savedDevice.getName(), savedDevice.getIpAddress(), savedDevice.getPort());
        return savedDevice;
    }

    /**
     * 批量添加设备
     * 
     * @param request 批量添加请求
     * @return 批量添加结果
     */
    @Transactional
    public BatchAddDevicesResponse batchAddDevices(BatchAddDevicesRequest request) {
        log.info("开始批量添加设备，总数: {}", request.getDevices().size());
        
        BatchAddDevicesResponse response = new BatchAddDevicesResponse();
        response.setTotalCount(request.getDevices().size());
        
        for (AddDeviceByIpRequest deviceRequest : request.getDevices()) {
            try {
                // 检查设备是否已存在（根据IP地址和端口进行判重）
                Optional<OnvifDevice> existingDevice = deviceRepository.findByIpAddressAndPort(
                    deviceRequest.getIpAddress(), deviceRequest.getPort());
                
                if (existingDevice.isPresent()) {
                    // 设备已存在，返回错误信息
                    String errorMessage = String.format("设备 %s:%d 已存在于设备管理中，无法重复添加", 
                        deviceRequest.getIpAddress(), deviceRequest.getPort());
                    
                    log.warn("设备重复添加: {}:{}", deviceRequest.getIpAddress(), deviceRequest.getPort());
                    
                    response.addFailedDevice(
                        deviceRequest.getIpAddress(), 
                        deviceRequest.getPort(), 
                        errorMessage, 
                        deviceRequest
                    );
                } else {
                    // 添加新设备
                    OnvifDevice device = addDeviceByIp(deviceRequest);
                    log.info("成功添加新设备: {}:{}", deviceRequest.getIpAddress(), deviceRequest.getPort());
                    response.addSuccessDevice(device);
                }
                
            } catch (Exception e) {
                log.error("添加设备失败 {}:{} - {}", 
                    deviceRequest.getIpAddress(), deviceRequest.getPort(), e.getMessage());
                
                response.addFailedDevice(
                    deviceRequest.getIpAddress(), 
                    deviceRequest.getPort(), 
                    e.getMessage(), 
                    deviceRequest
                );
                
                // 如果不忽略连接失败，则抛出异常
                if (!request.getIgnoreConnectionFailures()) {
                    throw new RuntimeException("批量添加设备失败: " + e.getMessage(), e);
                }
            }
        }
        
        log.info("批量添加设备完成 - 成功: {}, 失败: {}, 总数: {}", 
            response.getSuccessCount(), response.getFailureCount(), response.getTotalCount());
        
        return response;
    }

    /**
     * 更新设备
     * 
     * @param id 设备ID
     * @param device 设备信息
     * @return 更新的设备
     */
    @Transactional
    public OnvifDevice updateDevice(Long id, OnvifDevice device) {
        log.info("更新ONVIF设备: {}", id);
        
        OnvifDevice existingDevice = deviceRepository.findById(id)
            .orElseThrow(() -> new RuntimeException("设备不存在: " + id));
        
        // 检查IP地址和端口是否与其他设备冲突
        if (!existingDevice.getIpAddress().equals(device.getIpAddress()) || 
            !existingDevice.getPort().equals(device.getPort())) {
            
            boolean exists = deviceRepository.existsByIpAddressAndPortExcludingId(
                device.getIpAddress(), device.getPort(), id);
            if (exists) {
                throw new RuntimeException("设备地址冲突: " + device.getIpAddress() + ":" + device.getPort());
            }
        }
        
        // 更新设备信息
        existingDevice.setName(device.getName());
        existingDevice.setIpAddress(device.getIpAddress());
        existingDevice.setPort(device.getPort());
        existingDevice.setUsername(device.getUsername());
        existingDevice.setPassword(device.getPassword());
        existingDevice.setEnabled(device.getEnabled());
        existingDevice.setDescription(device.getDescription());
        
        OnvifDevice savedDevice = deviceRepository.save(existingDevice);
        
        // 如果连接信息发生变化，重新连接设备
        if (!existingDevice.getIpAddress().equals(device.getIpAddress()) || 
            !existingDevice.getPort().equals(device.getPort()) ||
            !StrUtil.equals(existingDevice.getUsername(), device.getUsername()) ||
            !StrUtil.equals(existingDevice.getPassword(), device.getPassword())) {
            
            connectAndUpdateDeviceInfo(savedDevice.getDeviceId());
        }
        
        return savedDevice;
    }

    /**
     * 删除设备
     * 
     * @param id 设备ID
     */
    @Transactional
    public void deleteDevice(Long id) {
        log.info("删除ONVIF设备: {}", id);
        
        OnvifDevice device = deviceRepository.findById(id)
            .orElseThrow(() -> new RuntimeException("设备不存在: " + id));
        
        // 删除设备的所有通道
        channelRepository.deleteByDevice(device);
        
        // 删除设备
        deviceRepository.delete(device);
    }

    /**
     * 启用/禁用设备
     * 
     * @param id 设备ID
     * @param enabled 是否启用
     * @return 更新的设备
     */
    @Transactional
    public OnvifDevice toggleDeviceEnabled(Long id, boolean enabled) {
        log.info("{}设备: {}", enabled ? "启用" : "禁用", id);
        
        OnvifDevice device = deviceRepository.findById(id)
            .orElseThrow(() -> new RuntimeException("设备不存在: " + id));
        
        device.setEnabled(enabled);
        if (!enabled) {
            device.setStatus(OnvifDevice.DeviceStatus.OFFLINE);
        }
        
        return deviceRepository.save(device);
    }

    /**
     * 测试设备连接
     * 
     * @param id 设备ID
     * @return 连接是否成功
     */
    public boolean testDeviceConnection(Long id) {
        OnvifDevice device = deviceRepository.findById(id)
            .orElseThrow(() -> new RuntimeException("设备不存在: " + id));
        
        return onvifClientService.testConnection(device);
    }
    
    /**
     * 测试设备连接
     * 
     * @param device 设备对象
     * @return 连接是否成功
     */
    public boolean testDeviceConnection(OnvifDevice device) {
        return onvifClientService.testConnection(device);
    }
    
    /**
     * 测试通道连接
     * 
     * @param channelId 通道ID
     * @return 连接是否成功
     */
    public boolean testChannelConnection(Long channelId) {
        OnvifChannel channel = channelRepository.findById(channelId)
            .orElseThrow(() -> new RuntimeException("通道不存在: " + channelId));
        
        OnvifDevice device = channel.getDevice();
        if (device == null) {
            log.warn("Channel {} is not associated with any device", channelId);
            return false;
        }
        
        // 首先测试设备连接
        boolean deviceConnected = onvifClientService.testConnection(device);
        if (!deviceConnected) {
            log.warn("Device {} associated with channel {} connection failed", device.getId(), channelId);
            return false;
        }
        
        // 检查通道的RTSP URL是否可用
        if (StrUtil.isEmpty(channel.getRtspUrl())) {
            log.warn("Channel {} has no RTSP URL configured", channelId);
            return false;
        }
        
        // 可以进一步测试RTSP流的连接性
        try {
            // 这里可以添加RTSP连接测试逻辑
            log.info("Channel {} connection test passed", channelId);
            return true;
        } catch (Exception e) {
            log.error("Channel {} RTSP connection test failed: {}", channelId, e.getMessage());
            return false;
        }
    }

    /**
     * 刷新设备信息
     * 
     * @param id 设备ID
     * @return 更新的设备
     */
    @Transactional
    public OnvifDevice refreshDeviceInfo(Long id) {
        log.info("刷新设备信息: {}", id);
        
        OnvifDevice device = deviceRepository.findById(id)
            .orElseThrow(() -> new RuntimeException("设备不存在: " + id));
        
        // 连接设备并更新信息
        connectAndUpdateDeviceInfo(String.valueOf(id));
        
        return deviceRepository.findById(id).orElse(device);
    }

    /**
     * 异步连接设备并更新设备信息
     * 
     * @param deviceId Device ID
     */
    @Async
    public void connectAndUpdateDeviceInfo(String deviceId) {
        long startTime = System.currentTimeMillis();
        Map<String, Object> discoveryResult = null;
        List<OnvifClientService.ProfileInfo> profiles = null;
        
        try {
            OnvifDevice device = deviceRepository.findByDeviceId(deviceId).orElse(null);
            if (device == null || !device.getEnabled()) {
                log.debug("设备不存在或已禁用，跳过连接: deviceId={}", deviceId);
                return;
            }
            
            log.info("开始连接ONVIF设备: {} - {}:{}", device.getName(), device.getIpAddress(), device.getPort());
            
            // 测试连接
            boolean connected = onvifClientService.testConnection(device);
            if (!connected) {
                log.warn("设备连接失败: {} - {}:{}", device.getName(), device.getIpAddress(), device.getPort());
                updateDeviceStatus(deviceId, OnvifDevice.DeviceStatus.OFFLINE);
                return;
            }
            
            log.info("设备连接成功: {}", device.getName());
            
            // 执行智能服务发现和能力分析
            discoveryResult = performIntelligentServiceDiscovery(device);
            
            // 获取设备信息
            OnvifClientService.DeviceInfo deviceInfo = onvifClientService.getDeviceInfo(device);
            if (deviceInfo != null) {
                updateDeviceInfo(deviceId, deviceInfo);
                log.info("设备信息更新成功: {} - 制造商: {}, 型号: {}", 
                    device.getName(), deviceInfo.getManufacturer(), deviceInfo.getModel());
            }
            
            // 使用优化策略获取通道配置文件
            profiles = getProfilesWithOptimizedStrategy(device, discoveryResult);
            if (profiles != null && !profiles.isEmpty()) {
                log.info("Device {} discovered {} channel profiles", device.getName(), profiles.size());
                
                // 详细记录每个配置文件信息
                for (int i = 0; i < profiles.size(); i++) {
                    OnvifClientService.ProfileInfo profile = profiles.get(i);
                    String maskedRtsp = profile.getRtspUrl() != null ? 
                        profile.getRtspUrl().replaceAll("://[^@]*@", "://***:***@") : "null";
                    log.info("配置文件 {}: 名称={}, Token={}, 视频编码={}, 分辨率={}x{}, RTSP={}", 
                        i + 1, profile.getName(), profile.getToken(), 
                        profile.getVideoEncoding(), profile.getVideoWidth(), profile.getVideoHeight(), maskedRtsp);
                }
                
                updateDeviceChannels(deviceId, profiles);
                log.info("Device {} channel information update completed", device.getName());
            } else {
                log.warn("Device {} found no channel profiles", device.getName());
                @SuppressWarnings("unchecked")
                Map<String, String> capabilities = (Map<String, String>) discoveryResult.get("capabilities");
                analyzeChannelDiscoveryFailure(device, capabilities);
            }
            
            // 更新设备状态为在线
            updateDeviceStatus(deviceId, OnvifDevice.DeviceStatus.ONLINE);
            log.info("设备 {} 连接和信息更新完成", device.getName());
            
            // 生成优化报告
            if (discoveryResult != null) {
                generateOptimizationReport(device, discoveryResult, profiles, startTime);
            }
            
        } catch (Exception e) {
            log.error("连接设备时发生错误: deviceId={}, 错误: {}", deviceId, e.getMessage(), e);
            updateDeviceStatus(deviceId, OnvifDevice.DeviceStatus.ERROR);
            
            // 即使出错也生成报告（用于问题分析）
            if (discoveryResult != null) {
                OnvifDevice device = deviceRepository.findByDeviceId(deviceId).orElse(null);
                if (device != null) {
                    generateOptimizationReport(device, discoveryResult, profiles, startTime);
                }
            }
        }
    }
    
    /**
     * 带重试机制的配置文件获取
     */
    private List<OnvifClientService.ProfileInfo> getProfilesWithRetry(OnvifDevice device, Map<String, String> capabilities) {
        int maxRetries = 3;
        int retryDelay = 1000; // 1秒
        
        for (int attempt = 1; attempt <= maxRetries; attempt++) {
            try {
                log.debug("尝试获取设备 {} 的配置文件，第 {} 次尝试", device.getName(), attempt);
                
                List<OnvifClientService.ProfileInfo> profiles = onvifClientService.getProfiles(device);
                if (profiles != null && !profiles.isEmpty()) {
                    log.info("第 {} 次尝试成功获取到 {} 个配置文件", attempt, profiles.size());
                    return profiles;
                }
                
                if (attempt < maxRetries) {
                    log.warn("第 {} 次尝试未获取到配置文件，{}ms后重试", attempt, retryDelay);
                    Thread.sleep(retryDelay);
                    retryDelay *= 2; // 指数退避
                }
                
            } catch (Exception e) {
                log.warn("第 {} 次获取配置文件失败: {}", attempt, e.getMessage());
                if (attempt < maxRetries) {
                    try {
                        Thread.sleep(retryDelay);
                        retryDelay *= 2;
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                        break;
                    }
                }
            }
        }
        
        log.error("经过 {} 次尝试仍无法获取设备 {} 的配置文件", maxRetries, device.getName());
        return null;
    }
    
    /**
     * 分析通道发现失败的原因
     */
    private void analyzeChannelDiscoveryFailure(OnvifDevice device, Map<String, String> capabilities) {
        log.warn("Analyzing reasons for device {} channel discovery failure:", device.getName());
        
        // 检查媒体服务支持
        if (capabilities == null || capabilities.isEmpty()) {
            log.warn("  - Unable to get device capabilities, possibly authentication issue or device doesn't support GetCapabilities");
        } else {
            String mediaService = (String) capabilities.get("Media");
            if (StrUtil.isEmpty(mediaService)) {
                log.warn("  - Device doesn't support Media service, cannot get media profiles");
            } else {
                log.info("  - Device supports Media service: {}", mediaService);
                log.warn("  - Possible reasons: 1.Authentication failed 2.GetProfiles call failed 3.Device has no profiles");
            }
        }
        
        // 记录设备连接信息用于调试
        log.debug("Device connection details - IP: {}, Port: {}, Username: {}, Service URL: {}", 
            device.getIpAddress(), device.getPort(), device.getUsername(), device.getServiceUrl());
        
        // 建议解决方案
        log.info("Suggested solutions:");
        log.info("  1. Check if device username and password are correct");
        log.info("  2. Confirm if device supports ONVIF Profile S");
        log.info("  3. Check if device has configured media profiles");
        log.info("  4. Try using configuration tools provided by device manufacturer");
    }
     
    /**
     * 增强的通道验证和RTSP URL处理
     */
    private String validateAndEnhanceRtspUrl(String originalUrl, OnvifDevice device) {
        if (StrUtil.isEmpty(originalUrl)) {
            log.warn("RTSP URL为空，尝试构建默认URL");
            return buildDefaultRtspUrl(device);
        }
        
        try {
            // 验证URL格式
            if (!originalUrl.toLowerCase().startsWith("rtsp://")) {
                log.warn("无效的RTSP URL格式: {}", originalUrl.replaceAll("://[^@]*@", "://***:***@"));
                return buildDefaultRtspUrl(device);
            }
            
            // 检查是否包含认证信息
            if (!originalUrl.contains("@")) {
                // 添加认证信息
                String enhancedUrl = originalUrl.replace("rtsp://", 
                    String.format("rtsp://%s:%s@", device.getUsername(), device.getPassword()));
                log.debug("为RTSP URL添加认证信息");
                return enhancedUrl;
            }
            
            return originalUrl;
            
        } catch (Exception e) {
            log.error("处理RTSP URL时发生错误: {}", e.getMessage());
            return buildDefaultRtspUrl(device);
        }
    }
    
    /**
     * 构建默认的RTSP URL
     */
    private String buildDefaultRtspUrl(OnvifDevice device) {
        // 常见的RTSP路径模式
        String[] commonPaths = {
            "/Streaming/Channels/101",
            "/cam/realmonitor?channel=1&subtype=0",
            "/h264/ch1/main/av_stream",
            "/stream1",
            "/live/ch1"
        };
        
        // 使用第一个作为默认路径
        String defaultPath = commonPaths[0];
        String defaultUrl = String.format("rtsp://%s:%s@%s:554%s", 
            device.getUsername(), device.getPassword(), device.getIpAddress(), defaultPath);
            
        log.info("构建默认RTSP URL，路径: {}", defaultPath);
        return defaultUrl;
    }
    
    /**
     * 验证通道配置文件的完整性
     */
    private boolean validateProfileCompleteness(OnvifClientService.ProfileInfo profile, int index) {
        List<String> issues = new ArrayList<>();
        
        if (StrUtil.isEmpty(profile.getToken())) {
            issues.add("Profile Token为空");
        }
        
        if (StrUtil.isEmpty(profile.getRtspUrl())) {
            issues.add("RTSP URL为空");
        }
        
        if (profile.getVideoWidth() == null || profile.getVideoHeight() == null || 
            profile.getVideoWidth() <= 0 || profile.getVideoHeight() <= 0) {
            issues.add("视频分辨率无效");
        }
        
        if (StrUtil.isEmpty(profile.getVideoEncoding())) {
            issues.add("视频编码信息缺失");
        }
        
        if (!issues.isEmpty()) {
            log.warn("配置文件 {} 存在问题: {}", index + 1, String.join(", ", issues));
            return false;
        }
        
        return true;
    }
     
    /**
     * 智能服务发现和能力分析
     */
    private Map<String, Object> performIntelligentServiceDiscovery(OnvifDevice device) {
        Map<String, Object> discoveryResult = new HashMap<>();
        
        try {
            log.info("开始智能服务发现: 设备 {}", device.getName());
            
            // 获取设备能力
            Map<String, Object> capabilities = onvifClientService.getDeviceCapabilities(device);
            discoveryResult.put("capabilities", capabilities);
            
            if (capabilities != null && !capabilities.isEmpty()) {
                log.info("设备 {} 支持的服务:", device.getName());
                
                // 分析媒体服务
                String mediaService = (String) capabilities.get("Media");
                if (StrUtil.isNotEmpty(mediaService)) {
                    log.info("  ✓ Media服务: {}", mediaService);
                    discoveryResult.put("hasMediaService", true);
                    discoveryResult.put("mediaServiceUrl", mediaService);
                } else {
                    log.warn("  ✗ 不支持Media服务");
                    discoveryResult.put("hasMediaService", false);
                }
                
                // 分析PTZ服务
                String ptzService = (String) capabilities.get("PTZ");
                if (StrUtil.isNotEmpty(ptzService)) {
                    log.info("  ✓ PTZ服务: {}", ptzService);
                    discoveryResult.put("hasPtzService", true);
                } else {
                    log.info("  - 不支持PTZ服务");
                    discoveryResult.put("hasPtzService", false);
                }
                
                // 分析成像服务
                String imagingService = (String) capabilities.get("Imaging");
                if (StrUtil.isNotEmpty(imagingService)) {
                    log.info("  ✓ Imaging服务: {}", imagingService);
                    discoveryResult.put("hasImagingService", true);
                } else {
                    log.info("  - 不支持Imaging服务");
                    discoveryResult.put("hasImagingService", false);
                }
                
                // 分析事件服务
                String eventsService = (String) capabilities.get("Events");
                if (StrUtil.isNotEmpty(eventsService)) {
                    log.info("  ✓ Events服务: {}", eventsService);
                    discoveryResult.put("hasEventsService", true);
                } else {
                    log.info("  - 不支持Events服务");
                    discoveryResult.put("hasEventsService", false);
                }
                
                // 检查厂商扩展
                capabilities.entrySet().stream()
                    .filter(entry -> !Arrays.asList("Media", "PTZ", "Imaging", "Events", "Device").contains(entry.getKey()))
                    .forEach(entry -> {
                        log.info("  ✓ 厂商扩展服务 {}: {}", entry.getKey(), entry.getValue());
                    });
                    
                discoveryResult.put("serviceCount", capabilities.size());
                
            } else {
                log.warn("设备 {} 无法获取能力信息", device.getName());
                discoveryResult.put("hasMediaService", false);
                discoveryResult.put("serviceCount", 0);
            }
            
        } catch (Exception e) {
            log.error("智能服务发现失败: {}", e.getMessage());
            discoveryResult.put("error", e.getMessage());
            discoveryResult.put("hasMediaService", false);
        }
        
        return discoveryResult;
    }
    
    /**
     * 基于服务发现结果优化通道获取策略
     */
    private List<OnvifClientService.ProfileInfo> getProfilesWithOptimizedStrategy(OnvifDevice device, Map<String, Object> discoveryResult) {
        Boolean hasMediaService = (Boolean) discoveryResult.get("hasMediaService");
        
        if (hasMediaService == null || !hasMediaService) {
            log.warn("Device doesn't support Media service, skipping channel acquisition");
            return null;
        }
        
        // 使用带重试机制的配置文件获取
        @SuppressWarnings("unchecked")
        Map<String, String> capabilities = (Map<String, String>) discoveryResult.get("capabilities");
        return getProfilesWithRetry(device, capabilities);
    }
     
    /**
     * 生成通道获取优化报告
     */
    private void generateOptimizationReport(OnvifDevice device, Map<String, Object> discoveryResult, 
                                           List<OnvifClientService.ProfileInfo> profiles, long startTime) {
        long endTime = System.currentTimeMillis();
        long duration = endTime - startTime;
        
        log.info("=== Device {} Channel Acquisition Optimization Report ===", device.getName());
        log.info("Total duration: {}ms", duration);
        
        // 服务发现结果
        Integer serviceCount = (Integer) discoveryResult.get("serviceCount");
        Boolean hasMediaService = (Boolean) discoveryResult.get("hasMediaService");
        Boolean hasPtzService = (Boolean) discoveryResult.get("hasPtzService");
        Boolean hasImagingService = (Boolean) discoveryResult.get("hasImagingService");
        Boolean hasEventsService = (Boolean) discoveryResult.get("hasEventsService");
        
        log.info("Service discovery: Found {} services", serviceCount != null ? serviceCount : 0);
        log.info("  Media service: {}", hasMediaService != null && hasMediaService ? "✓" : "✗");
        log.info("  PTZ service: {}", hasPtzService != null && hasPtzService ? "✓" : "-");
        log.info("  Imaging service: {}", hasImagingService != null && hasImagingService ? "✓" : "-");
        log.info("  Events service: {}", hasEventsService != null && hasEventsService ? "✓" : "-");
        
        // 通道获取结果
        if (profiles != null && !profiles.isEmpty()) {
            log.info("Channel discovery: Successfully acquired {} channel profiles", profiles.size());
            
            // 统计视频编码类型
            Map<String, Long> encodingStats = profiles.stream()
                .filter(p -> StrUtil.isNotEmpty(p.getVideoEncoding()))
                .collect(Collectors.groupingBy(
                    OnvifClientService.ProfileInfo::getVideoEncoding,
                    Collectors.counting()
                ));
            
            if (!encodingStats.isEmpty()) {
                log.info("Video encoding statistics: {}", encodingStats);
            }
            
            // 统计分辨率
            Map<String, Long> resolutionStats = profiles.stream()
                .filter(p -> p.getVideoWidth() != null && p.getVideoHeight() != null && 
                           p.getVideoWidth() > 0 && p.getVideoHeight() > 0)
                .collect(Collectors.groupingBy(
                    p -> p.getVideoWidth() + "x" + p.getVideoHeight(),
                    Collectors.counting()
                ));
            
            if (!resolutionStats.isEmpty()) {
                log.info("Resolution statistics: {}", resolutionStats);
            }
            
        } else {
            log.warn("Channel discovery: No channel profiles acquired");
        }
        
        // 优化建议
        if (hasMediaService == null || !hasMediaService) {
            log.warn("Optimization suggestion: Device doesn't support standard Media service, recommend checking device ONVIF compatibility");
        } else if (profiles == null || profiles.isEmpty()) {
            log.warn("Optimization suggestion: Device supports Media service but has no profiles, recommend checking device configuration");
        } else {
            log.info("Optimization suggestion: Device configuration is good, channel acquisition successful");
        }
        
        log.info("=== Optimization Report End ===");
    }

    /**
     * 更新设备状态
     * 
     * @param deviceId Device ID
     * @param status 设备状态
     */
    @Transactional
    public void updateDeviceStatus(String deviceId, OnvifDevice.DeviceStatus status) {
        OnvifDevice device = deviceRepository.findByDeviceId(deviceId).orElse(null);
        if (device != null) {
            device.setStatus(status);
            if (status == OnvifDevice.DeviceStatus.ONLINE) {
                device.setLastOnlineTime(LocalDateTime.now());
            }
            deviceRepository.save(device);
        }
    }

    /**
     * 更新设备信息
     * 
     * @param deviceId Device ID
     * @param deviceInfo 设备信息
     */
    @Transactional
    public void updateDeviceInfo(String deviceId, OnvifClientService.DeviceInfo deviceInfo) {
        OnvifDevice device = deviceRepository.findByDeviceId(deviceId).orElse(null);
        if (device != null) {
            if (StrUtil.isNotEmpty(deviceInfo.getManufacturer())) {
                device.setManufacturer(deviceInfo.getManufacturer());
            }
            if (StrUtil.isNotEmpty(deviceInfo.getModel())) {
                device.setModel(deviceInfo.getModel());
            }
            if (StrUtil.isNotEmpty(deviceInfo.getFirmwareVersion())) {
                device.setFirmwareVersion(deviceInfo.getFirmwareVersion());
            }
            if (StrUtil.isNotEmpty(deviceInfo.getSerialNumber())) {
                device.setSerialNumber(deviceInfo.getSerialNumber());
            }
            if (StrUtil.isNotEmpty(deviceInfo.getHardwareId())) {
                device.setHardwareId(deviceInfo.getHardwareId());
            }
            deviceRepository.save(device);
        }
    }

    /**
     * 更新设备通道
     * 
     * @param deviceId Device ID
     * @param profiles 配置文件列表
     */
    @Transactional
    public void updateDeviceChannels(String deviceId, List<OnvifClientService.ProfileInfo> profiles) {
        OnvifDevice device = deviceRepository.findByDeviceId(deviceId).orElse(null);
        if (device == null) {
            log.error("Device does not exist, cannot update channels: deviceId={}", deviceId);
            return;
        }
        
        log.info("Starting to update device channels: deviceId={}, device name={}, profile count={}", 
            deviceId, device.getName(), profiles.size());
        
        // 验证配置文件
        if (profiles == null || profiles.isEmpty()) {
            log.warn("Profile list is empty, clearing device channels: deviceId={}", deviceId);
            channelRepository.deleteByDevice(device);
            return;
        }
        
        // 获取现有通道，用于比较
        List<OnvifChannel> existingChannels = channelRepository.findByDevice(device);
        log.info("Device existing channel count: {}", existingChannels.size());
        
        // 删除现有通道
        if (!existingChannels.isEmpty()) {
            log.info("Deleting {} existing channels", existingChannels.size());
            channelRepository.deleteByDevice(device);
            // 强制刷新持久化上下文
            channelRepository.flush();
            log.info("Existing channels deleted and flushed");
        }
        
        // 创建新通道
        List<OnvifChannel> newChannels = new ArrayList<>();
        int successCount = 0;
        int failureCount = 0;
        
        for (int i = 0; i < profiles.size(); i++) {
            try {
                OnvifClientService.ProfileInfo profile = profiles.get(i);
                log.debug("Processing profile {}/{}: token={}, name={}", 
                    i + 1, profiles.size(), profile.getToken(), profile.getName());
                
                // 加强验证profile token不能为空
                if (profile.getToken() == null) {
                    log.warn("Profile {} has null token, skipping: name={}", i + 1, profile.getName());
                    failureCount++;
                    continue;
                }
                
                String profileToken = profile.getToken().trim();
                
                // 验证处理后的token不能为空
                if (profileToken.isEmpty()) {
                    log.warn("Profile {} token is empty after trim, skipping: name={}", i + 1, profile.getName());
                    failureCount++;
                    continue;
                }
                
                // 验证token长度（数据库字段长度限制为200）
                if (profileToken.length() > 200) {
                    log.warn("Profile {} token too long ({}), truncating: name={}", 
                        i + 1, profileToken.length(), profile.getName());
                    profileToken = profileToken.substring(0, 200);
                }
                
                OnvifChannel channel = new OnvifChannel();
                channel.setDevice(device);
                channel.setChannelNo(i + 1);
                
                // 设置channelToken和profileToken
                channel.setChannelToken(profileToken); // 映射到数据库的channel_token字段
                channel.setProfileToken(profileToken); // 映射到数据库的profile_token字段
                channel.setName(generateChannelName(profile, i + 1, device));
                channel.setRtspUrl(validateAndCleanRtspUrl(profile.getRtspUrl()));
                channel.setVideoEncoding(validateVideoEncoding(profile.getVideoEncoding()));
                channel.setAudioEncoding(validateAudioEncoding(profile.getAudioEncoding()));
                channel.setVideoWidth(validateDimension(profile.getVideoWidth(), "width"));
                channel.setVideoHeight(validateDimension(profile.getVideoHeight(), "height"));
                channel.setFrameRate(validateFrameRate(profile.getFrameRate()));
                channel.setBitRate(validateBitRate(profile.getBitRate()));
                channel.setEnabled(true);
                channel.setStatus(OnvifChannel.ChannelStatus.ACTIVE);
                
                // 最终验证必要字段
                if (channel.getProfileToken() == null || channel.getProfileToken().trim().isEmpty()) {
                    log.error("Channel profile token is null or empty after processing, skipping channel {}", i + 1);
                    failureCount++;
                    continue;
                }
                
                newChannels.add(channel);
                successCount++;
                
                log.debug("Successfully created channel object: channelNo={}, name={}, token={}, rtsp={}", 
                    channel.getChannelNo(), channel.getName(), channel.getProfileToken(), 
                    channel.getRtspUrl() != null ? "✓" : "✗");
                    
            } catch (Exception e) {
                log.error("Failed to create channel (profile {}): {}", i + 1, e.getMessage(), e);
                failureCount++;
            }
        }
        
        // 应用增强的通道验证和优化
        log.info("Applying channel validation and optimization, original channel count: {}", newChannels.size());
        List<OnvifChannel> optimizedChannels = validateAndOptimizeChannels(newChannels, device);
        
        // 批量保存优化后的通道
        if (!optimizedChannels.isEmpty()) {
            // 最终验证所有通道的必要字段
            List<OnvifChannel> finalValidChannels = optimizedChannels.stream()
                .filter(channel -> {
                    if (channel.getProfileToken() == null || channel.getProfileToken().trim().isEmpty()) {
                        log.error("Final validation failed: Channel {} has invalid profile token", 
                            channel.getChannelNo());
                        return false;
                    }
                    if (channel.getDevice() == null) {
                        log.error("Final validation failed: Channel {} has no device association", 
                            channel.getChannelNo());
                        return false;
                    }
                    return true;
                })
                .collect(java.util.stream.Collectors.toList());
            
            if (finalValidChannels.isEmpty()) {
                log.warn("No valid channels to save after final validation");
                return;
            }
            
            try {
                log.info("Starting to save {} channels to database", finalValidChannels.size());
                List<OnvifChannel> savedChannels = channelRepository.saveAll(finalValidChannels);
                // 强制刷新持久化上下文，确保数据立即写入数据库
                channelRepository.flush();
                log.info("Batch save channels completed and flushed, saved count: {}", savedChannels.size());
                
                // 验证保存结果
                List<OnvifChannel> verifyChannels = channelRepository.findByDevice(device);
                log.info("Verification: Found {} channels in database after save", verifyChannels.size());
                
                // 记录每个保存的通道
                for (OnvifChannel savedChannel : savedChannels) {
                    log.debug("Successfully saved channel: id={}, name={}, token={}, rtsp={}", 
                        savedChannel.getId(), savedChannel.getName(), 
                        savedChannel.getProfileToken(), 
                        StrUtil.isNotEmpty(savedChannel.getRtspUrl()) ? "✓" : "✗");
                }
            } catch (Exception e) {
                log.error("Failed to save channels to database: {}", e.getMessage(), e);
                throw new RuntimeException("Failed to save channels to database: " + e.getMessage(), e);
            }
        } else {
            log.warn("No valid channels to save after optimization");
        }
        
        log.info("Device channel update completed: deviceId={}, device name={}, success={}, failed={}, total={}", 
            deviceId, device.getName(), successCount, failureCount, profiles.size());
        
        // 如果所有通道都创建失败，记录警告
        if (successCount == 0 && failureCount > 0) {
            log.warn("All device channels creation failed: deviceId={}, failed count={}", deviceId, failureCount);
        }
    }
    
    /**
     * 生成通道名称
     */
    private String generateChannelName(OnvifClientService.ProfileInfo profile, int channelNo, OnvifDevice device) {
        // 优先使用Profile的名称
        if (StrUtil.isNotEmpty(profile.getName())) {
            String name = profile.getName().trim();
            // 如果名称过长，截取前50个字符
            if (name.length() > 50) {
                name = name.substring(0, 50) + "...";
            }
            return name;
        }
        
        // 根据设备类型生成默认名称
        boolean isHikvision = isHikvisionDevice(device);
        if (isHikvision) {
            return "通道" + channelNo;
        } else {
            return "Profile_" + channelNo;
        }
    }
    
    /**
     * 验证和清理RTSP URL
     */
    private String validateAndCleanRtspUrl(String rtspUrl) {
        if (StrUtil.isEmpty(rtspUrl)) {
            return null;
        }
        
        String url = rtspUrl.trim();
        
        // 检查URL格式
        if (!url.toLowerCase().startsWith("rtsp://")) {
            log.warn("RTSP URL格式可能不正确: {}", url);
        }
        
        // 限制URL长度
        if (url.length() > 500) {
            log.warn("RTSP URL过长，截取前500个字符: 原长度={}", url.length());
            url = url.substring(0, 500);
        }
        
        return url;
    }
    
    /**
     * 验证视频编码
     */
    private String validateVideoEncoding(String encoding) {
        if (StrUtil.isEmpty(encoding)) {
            return "Unknown";
        }
        
        String cleanEncoding = encoding.trim().toUpperCase();
        
        // 标准化常见编码名称
        switch (cleanEncoding) {
            case "H264":
            case "H.264":
                return "H264";
            case "H265":
            case "H.265":
            case "HEVC":
                return "H265";
            case "MJPEG":
            case "MOTION-JPEG":
                return "MJPEG";
            default:
                return cleanEncoding.length() > 20 ? cleanEncoding.substring(0, 20) : cleanEncoding;
        }
    }
    
    /**
     * 验证音频编码
     */
    private String validateAudioEncoding(String encoding) {
        if (StrUtil.isEmpty(encoding)) {
            return null;
        }
        
        String cleanEncoding = encoding.trim().toUpperCase();
        
        // 标准化常见音频编码名称
        switch (cleanEncoding) {
            case "AAC":
            case "AAC-LC":
                return "AAC";
            case "G711":
            case "G.711":
            case "PCMU":
            case "PCMA":
                return "G711";
            case "G726":
            case "G.726":
                return "G726";
            default:
                return cleanEncoding.length() > 20 ? cleanEncoding.substring(0, 20) : cleanEncoding;
        }
    }
    
    /**
     * 验证尺寸参数
     */
    private Integer validateDimension(Integer dimension, String type) {
        if (dimension == null || dimension <= 0) {
            return null;
        }
        
        // 检查合理范围
        if (dimension > 7680) { // 8K分辨率上限
            log.warn("{}参数过大，可能不正确: {}", type, dimension);
        }
        
        return dimension;
    }
    
    /**
     * 验证帧率
     */
    private Integer validateFrameRate(Integer frameRate) {
        if (frameRate == null || frameRate <= 0) {
            return null;
        }
        
        // 检查合理范围
        if (frameRate > 120) {
            log.warn("帧率参数过大，可能不正确: {}", frameRate);
        }
        
        return frameRate;
    }
    
    /**
     * 验证比特率
     */
    private Integer validateBitRate(Integer bitRate) {
        if (bitRate == null || bitRate <= 0) {
            return null;
        }
        
        // 检查合理范围 (单位: bps)
        if (bitRate > 100_000_000) { // 100Mbps上限
            log.warn("比特率参数过大，可能不正确: {}", bitRate);
        }
        
        return bitRate;
    }

    /**
     * 获取设备统计信息
     * 
     * @return 统计信息
     */
    public DeviceStatistics getDeviceStatistics() {
        long totalDevices = deviceRepository.count();
        long onlineDevices = deviceRepository.countOnlineDevices();
        long offlineDevices = deviceRepository.countOfflineDevices();
        long enabledDevices = deviceRepository.countEnabledDevices();
        long disabledDevices = deviceRepository.countDisabledDevices();
        long totalChannels = channelRepository.count();
        
        return new DeviceStatistics(totalDevices, onlineDevices, offlineDevices, 
                                   enabledDevices, disabledDevices, totalChannels);
    }

    /**
     * 设备统计信息
     */
    /**
     * 启用/禁用通道
     * 
     * @param id Channel ID
     * @param enabled 是否启用
     * @return 更新的通道
     */
    @Transactional
    public OnvifChannel toggleChannelEnabled(Long id, boolean enabled) {
        log.info("{} channel: {}", enabled ? "Enable" : "Disable", id);
        
        OnvifChannel channel = channelRepository.findById(id)
            .orElseThrow(() -> new RuntimeException("Channel not found: " + id));
        
        channel.setEnabled(enabled);
        if (!enabled) {
            channel.setStatus(OnvifChannel.ChannelStatus.INACTIVE);
        }
        
        return channelRepository.save(channel);
    }

    public static class DeviceStatistics {
        private final long totalDevices;
        private final long onlineDevices;
        private final long offlineDevices;
        private final long enabledDevices;
        private final long disabledDevices;
        private final long totalChannels;

        public DeviceStatistics(long totalDevices, long onlineDevices, long offlineDevices, 
                              long enabledDevices, long disabledDevices, long totalChannels) {
            this.totalDevices = totalDevices;
            this.onlineDevices = onlineDevices;
            this.offlineDevices = offlineDevices;
            this.enabledDevices = enabledDevices;
            this.disabledDevices = disabledDevices;
            this.totalChannels = totalChannels;
        }

        public long getTotalDevices() { return totalDevices; }
        public long getOnlineDevices() { return onlineDevices; }
        public long getOfflineDevices() { return offlineDevices; }
        public long getEnabledDevices() { return enabledDevices; }
        public long getDisabledDevices() { return disabledDevices; }
        public long getTotalChannels() { return totalChannels; }
    }
    
    /**
     * 获取所有通道
     * 
     * @return Channel list
     */
    public List<OnvifChannel> getAllChannels() {
        return channelRepository.findAll();
    }
    
    /**
     * 根据ID获取通道
     * 
     * @param id Channel ID
     * @return 通道信息
     */
    public Optional<OnvifChannel> getChannelById(Long id) {
        return channelRepository.findById(id);
    }
    
    /**
     * 根据设备ID获取通道列表
     * 
     * @param deviceId Device ID
     * @return Channel list
     */
    public List<OnvifChannel> getChannelsByDeviceId(Long deviceId) {
        OnvifDevice device = deviceRepository.findById(deviceId).orElse(null);
        if (device == null) {
            return List.of();
        }
        return channelRepository.findByDevice(device);
    }
    
    /**
     * 根据设备deviceId（字符串）获取通道列表
     * 
     * @param deviceId 设备deviceId字符串
     * @return 通道列表
     */
    public List<OnvifChannel> getChannelsByDeviceIdString(String deviceId) {
        OnvifDevice device = deviceRepository.findByDeviceId(deviceId).orElse(null);
        if (device == null) {
            return List.of();
        }
        return channelRepository.findByDevice(device);
    }
    
    /**
     * 获取活跃状态的通道列表
     * 
     * @return 活跃通道列表
     */
    public List<OnvifChannel> getActiveChannels() {
        return channelRepository.findByStatus(OnvifChannel.ChannelStatus.ACTIVE);
    }
    
    /**
     * 根据状态获取通道列表
     * 
     * @param status 通道状态
     * @return 通道列表
     */
    public List<OnvifChannel> getChannelsByStatus(OnvifChannel.ChannelStatus status) {
        return channelRepository.findByStatus(status);
    }
    
    /**
     * 获取设备的通道数量
     * 
     * @param deviceId Device ID
     * @return 通道数量
     */
    public long getChannelCountByDevice(Long deviceId) {
        OnvifDevice device = deviceRepository.findById(deviceId).orElse(null);
        if (device == null) {
            return 0;
        }
        return channelRepository.countByDevice(device);
    }
    
    /**
     * 获取设备的活跃通道数量
     * 
     * @param deviceId Device ID
     * @return 活跃通道数量
     */
    public long getActiveChannelCountByDevice(Long deviceId) {
        OnvifDevice device = deviceRepository.findById(deviceId).orElse(null);
        if (device == null) {
            return 0;
        }
        return channelRepository.countByDeviceAndStatus(device, OnvifChannel.ChannelStatus.ACTIVE);
    }
    
    /**
     * 刷新设备通道
     * 
     * @param deviceId Device ID
     * @return Updated channel列表
     */
    @Transactional
    public List<OnvifChannel> refreshChannelsByDevice(String deviceId) {
        long refreshStartTime = System.currentTimeMillis();
        log.info("=== Device Channel Refresh Diagnosis Start ===");
        log.info("Device ID: {}", deviceId);
        log.info("Refresh start timestamp: {}", refreshStartTime);
        log.info("Current system time: {}", new java.util.Date());
        
        log.info("Starting device channel refresh: deviceId={}", deviceId);
        
        log.info(">>> Step 1: Find device information");
        OnvifDevice device = deviceRepository.findByDeviceId(deviceId)
            .orElseThrow(() -> new RuntimeException("Device not found: " + deviceId));
        
        log.info("✓ Found device information:");
        log.info("- Device address: {}:{}", device.getIpAddress(), device.getPort());
        log.info("- Device name: {}", device.getName());
        log.info("- Manufacturer: {}", device.getManufacturer());
        log.info("- Model: {}", device.getModel());
        log.info("- Enabled status: {}", device.getEnabled());
        log.info("- Create time: {}", device.getCreateTime());
        log.info("- Update time: {}", device.getUpdateTime());
        log.info("- Authentication info: username={}, password={}", 
            device.getUsername() != null ? device.getUsername() : "null", 
            device.getPassword() != null ? "[Set]" : "null");
        
        // 检查设备是否启用
        log.info(">>> Step 2: Check device status");
        if (!device.getEnabled()) {
            log.warn("✗ Device is disabled: deviceId={}", deviceId);
            throw new RuntimeException("Device is disabled, please enable device first before refreshing channels");
        }
        log.info("✓ Device is enabled");
        
        // Check authentication info
        log.info(">>> Step 3: Check authentication information");
        if (device.getUsername() == null || device.getPassword() == null || 
            device.getUsername().trim().isEmpty() || device.getPassword().trim().isEmpty()) {
            log.error("✗ Device authentication information missing: deviceId={}, username={}, password={}", 
                deviceId, device.getUsername(), device.getPassword() != null ? "[Set]" : "null");
            throw new RuntimeException("Device authentication information missing");
        }
        log.info("✓ Authentication information complete");
        
        // 设备类型检测和认证策略分析
        log.info(">>> Step 4: Device type detection and authentication strategy analysis");
        String deviceType = detectDeviceType(device);
        boolean isHikvisionDevice = "hikvision".equals(deviceType);
        boolean isDahuaDevice = "dahua".equals(deviceType);
        
        log.info("Device type detection result: {}:{} - {}", device.getIpAddress(), device.getPort(), 
            deviceType != null ? deviceType.toUpperCase() + " device" : "Generic ONVIF device");
        
        // 记录认证策略选择过程
        logAuthenticationStrategy(device, deviceType);
        
        if (isHikvisionDevice) {
            log.info("Hikvision device will use ONVIF standard authentication strategy");
        } else if (isDahuaDevice) {
            log.info("Dahua device will use ONVIF standard authentication strategy");
        } else {
            log.info("Generic device will use ONVIF standard authentication strategy");
        }
        log.info("Authentication priority: WS-Security > NoAuth (compliant with ONVIF standard)");
        
        // Test device connection first，使用优化的认证策略
        log.info(">>> Step 5: Test device connection and authentication");
        log.info("Starting device connection test: {}:{}", device.getIpAddress(), device.getPort());
        int connectionRetries = isHikvisionDevice ? 3 : (isDahuaDevice ? 3 : 2); // 根据设备类型调整重试次数
        log.info("Connection retry strategy: max retries={}, device type={}", connectionRetries, deviceType != null ? deviceType : "generic");
        
        // 记录认证信息（不记录密码明文）
        log.info("Authentication information verification:");
        log.info("- Username: {}", device.getUsername());
        log.info("- Password length: {} characters", device.getPassword() != null ? device.getPassword().length() : 0);
        log.info("- Service URL: {}", device.getServiceUrl());
        
        // 分析可能的认证方式
        analyzeAuthenticationMethods(device, deviceType);
        
        for (int retry = 1; retry <= connectionRetries; retry++) {
            try {
                if (retry > 1) {
                    log.info("Device connection retry {}/{}: {}:{}", retry, connectionRetries, 
                        device.getIpAddress(), device.getPort());
                    int waitTime = Math.min(retry * 600, 1500); // 优化等待时间：600ms、1200ms，最大1.5秒
                    log.info("Retry wait time: {}ms", waitTime);
                    Thread.sleep(waitTime);
                }
                
                log.info("Starting connection test (attempt {}): {}:{}", retry, device.getIpAddress(), device.getPort());
                long connectionStartTime = System.currentTimeMillis();
                
                boolean isConnected = onvifClientService.testConnection(device);
                long connectionTime = System.currentTimeMillis() - connectionStartTime;
                
                if (!isConnected) {
                    log.warn("✗ Device connection test failed (attempt {}): {}:{}, duration: {}ms", 
                        retry, device.getIpAddress(), device.getPort(), connectionTime);
                    
                    if (retry < connectionRetries) {
                        log.warn("Preparing to retry connection, remaining retries: {}", connectionRetries - retry);
                        continue;
                    }
                    
                    log.error("✗ Device connection test final failure: {}:{}", device.getIpAddress(), device.getPort());
                    log.error("Connection failure analysis:");
                    log.error("1. Network connection issue - device unreachable or high network latency");
                    log.error("2. Port issue - incorrect ONVIF service port or blocked by firewall");
                    log.error("3. Authentication issue - incorrect username/password or mismatched authentication method");
                    log.error("4. Device issue - ONVIF service not enabled or device malfunction");
                    log.error("5. Protocol issue - device does not support standard ONVIF protocol");
                    
                    throw new RuntimeException("Unable to connect to device, please check device network connection, IP address, port and authentication information");
                }
                
                log.info("✓ Device connection test successful: {}:{} (attempt {}), duration: {}ms", 
                    device.getIpAddress(), device.getPort(), retry, connectionTime);
                
                // 记录连接成功的认证方式（如果可以获取到）
                logSuccessfulAuthentication(device, retry, connectionTime);
                break; // 连接成功，跳出重试循环
                
            } catch (InterruptedException ie) {
                Thread.currentThread().interrupt();
                log.error("Connection test interrupted");
                throw new RuntimeException("Connection test interrupted", ie);
            } catch (Exception e) {
                long connectionTime = System.currentTimeMillis() - System.currentTimeMillis();
                log.error("✗ Device connection test exception (attempt {}): {}:{}, duration: {}ms", 
                    retry, device.getIpAddress(), device.getPort(), connectionTime);
                log.error("Exception type: {}", e.getClass().getSimpleName());
                log.error("Exception message: {}", e.getMessage());
                
                // 分析异常类型
                String errorAnalysis = analyzeConnectionError(e);
                log.error("Exception analysis: {}", errorAnalysis);
                
                boolean isRetriableError = e.getMessage() != null && 
                     (e.getMessage().contains("Unexpected end of file") ||
                      e.getMessage().contains("Connection reset") ||
                      e.getMessage().contains("timeout") ||
                      e.getMessage().contains("SocketTimeoutException") ||
                      e.getMessage().contains("ConnectException"));
                
                if (retry < connectionRetries && isRetriableError) {
                    log.warn("Encountered retriable network error, preparing to retry: {}:{}", device.getIpAddress(), device.getPort());
                    log.warn("Remaining retry attempts: {}", connectionRetries - retry);
                    continue;
                }
                
                log.error("Device connection test final failure: {}:{}", device.getIpAddress(), device.getPort());
                throw new RuntimeException("Device connection test failed: " + errorAnalysis, e);
            }
        }
        
        // Get device channels，使用标准ONVIF协议和优化的认证策略
        log.info(">>> Step 6: Get device profiles (using standard ONVIF protocol)");
        List<OnvifClientService.ProfileInfo> profiles = null;
        int profileRetries = isHikvisionDevice ? 3 : (isDahuaDevice ? 3 : 2); // 根据设备类型调整重试次数
        log.info("Profile retrieval retry strategy: max retries={}, retry interval=1200ms, device type={}", 
            profileRetries, deviceType != null ? deviceType : "generic");
        log.info("Standard ONVIF protocol: using GetProfiles request to get media profiles");
        log.info("ONVIF Media service: accessing media service endpoint through WS-Security authentication");
        
        // 记录优化后的认证策略优先级
        log.info("Authentication strategy priority (optimized):");
        if (isHikvisionDevice) {
            log.info("1. HikvisionDigest authentication (priority 0 - Hikvision specific Digest)");
            log.info("2. StandardDigest authentication (priority 1 - standard ONVIF Digest)");
            log.info("3. Basic authentication (priority 3 - HTTP basic authentication)");
            log.info("4. NoAuth authentication (priority 999 - no authentication)");
        } else if (isDahuaDevice) {
            log.info("1. StandardDigest authentication (priority 1 - standard ONVIF Digest)");
            log.info("2. Basic authentication (priority 3 - HTTP basic authentication)");
            log.info("3. NoAuth authentication (priority 999 - no authentication)");
        } else {
            log.info("1. StandardDigest authentication (priority 1 - standard ONVIF Digest)");
            log.info("2. Basic authentication (priority 3 - HTTP basic authentication)");
            log.info("3. NoAuth authentication (priority 999 - no authentication)");
        }
        
        // 增强的错误诊断信息
        Map<String, Object> diagnosticInfo = new HashMap<>();
        diagnosticInfo.put("deviceType", isHikvisionDevice ? "Hikvision" : "Generic ONVIF");
        diagnosticInfo.put("retryAttempts", 0);
        diagnosticInfo.put("errors", new ArrayList<String>());
        diagnosticInfo.put("warnings", new ArrayList<String>());
        
        long profilesStartTime = System.currentTimeMillis();
        for (int retry = 1; retry <= profileRetries; retry++) {
            try {
                if (retry > 1) {
                    log.info("Profile retrieval retry {}/{}: {}:{}", retry, profileRetries, 
                        device.getIpAddress(), device.getPort());
                    Thread.sleep(1200); // 优化重试等待时间为1.2秒
                }
                
                long singleAttemptStart = System.currentTimeMillis();
                log.info("Starting device profile retrieval: {}:{} (attempt {})", device.getIpAddress(), device.getPort(), retry);
                profiles = onvifClientService.getProfiles(device);
                long singleAttemptTime = System.currentTimeMillis() - singleAttemptStart;
                log.info("Profile retrieval attempt {} completed, duration: {}ms", retry, singleAttemptTime);
                
                if (profiles == null) {
                    if (retry < profileRetries) {
                        log.warn("Device profile retrieval returned null, preparing to retry: {}:{}", device.getIpAddress(), device.getPort());
                        continue;
                    }
                    log.error("Device profile retrieval returned null: {}:{}", device.getIpAddress(), device.getPort());
                    throw new RuntimeException("Device profile retrieval failed, returned null result");
                }
                
                log.info("Successfully retrieved {} profiles: {}:{} (attempt {})", 
                    profiles.size(), device.getIpAddress(), device.getPort(), retry);
                break; // 成功获取，跳出重试循环
                
            } catch (InterruptedException ie) {
                Thread.currentThread().interrupt();
                throw new RuntimeException("Profile retrieval interrupted", ie);
            } catch (Exception e) {
                long attemptTime = System.currentTimeMillis() - profilesStartTime;
                log.error("Exception occurred while retrieving device profiles (attempt {}/{}): {}:{}", 
                    retry, profileRetries, device.getIpAddress(), device.getPort());
                log.error("Exception type: {}", e.getClass().getSimpleName());
                log.error("Exception message: {}", e.getMessage());
                log.error("Current attempt duration: {}ms", attemptTime);
                
                boolean isRetriableError = e.getMessage() != null && 
                     (e.getMessage().contains("timeout") ||
                      e.getMessage().contains("Connection reset") ||
                      e.getMessage().contains("Media service") ||
                      e.getMessage().contains("Unexpected end of file"));
                
                if (retry < profileRetries && isRetriableError) {
                    log.warn("Encountered retriable error, preparing to retry: {}:{}", device.getIpAddress(), device.getPort());
                    log.warn("Remaining retry attempts: {}", profileRetries - retry);
                    continue;
                }
                
                // 最终失败，提供详细的错误分析
                long totalTime = System.currentTimeMillis() - refreshStartTime;
                log.error("=== Profile Retrieval Final Failure ===");
                log.error("Device: {}:{} ({})", device.getIpAddress(), device.getPort(), device.getName());
                log.error("Total retry attempts: {}", retry);
                log.error("Total duration: {}ms", totalTime);
                log.error("Is retriable error: {}", isRetriableError);
                
                String errorMessage = analyzeProfileError(e);
                log.error("Error analysis: {}", errorMessage);
                throw new RuntimeException(errorMessage, e);
            }
        }
        
        // 处理获取到的配置文件
        long profilesTime = System.currentTimeMillis() - profilesStartTime;
        log.info(">>> Step 7: Process profile retrieval results");
        log.info("Total profile retrieval duration: {}ms", profilesTime);
        
        if (profiles.isEmpty()) {
            log.warn("✗ Device returned no profiles: {}:{}", device.getIpAddress(), device.getPort());
            log.warn("Possible reasons:");
            log.warn("1. Device has no media profiles configured");
            log.warn("2. Device ONVIF service exception");
            log.warn("3. Network connection issues causing retrieval failure");
            log.warn("4. Insufficient authentication permissions");
            // 清空现有通道
            channelRepository.deleteByDevice(device);
            log.info("Cleared existing channels for device: deviceId={}", deviceId);
            return new ArrayList<>();
        }
        
        log.info("✓ Successfully retrieved {} profiles", profiles.size());
        
        // 记录每个配置文件的详细信息
        log.info(">>> Step 8: Analyze profile details");
        int validRtspCount = 0;
        for (int i = 0; i < profiles.size(); i++) {
            OnvifClientService.ProfileInfo profile = profiles.get(i);
            boolean hasRtsp = profile.getRtspUrl() != null && !profile.getRtspUrl().trim().isEmpty();
            if (hasRtsp) validRtspCount++;
            
            log.info("Profile {}: token={}, name={}, RTSP={}", 
                i + 1, profile.getToken(), profile.getName(), 
                hasRtsp ? "✓" : "✗");
            if (hasRtsp) {
                String rtspUrl = profile.getRtspUrl();
                // 隐藏RTSP URL中的密码信息
                String maskedUrl = rtspUrl.replaceAll("://[^@]*@", "://***:***@");
                log.info("  RTSP URL: {}", maskedUrl.length() > 80 ? 
                    maskedUrl.substring(0, 80) + "..." : maskedUrl);
            }
        }
        log.info("Profile statistics: Total={}, Valid RTSP={}, Success rate={}%", 
            profiles.size(), validRtspCount, 
            profiles.size() > 0 ? (validRtspCount * 100 / profiles.size()) : 0);
        
        // 更新设备通道
        log.info(">>> Step 9: Update device channels");
        long channelUpdateStartTime = System.currentTimeMillis();
        try {
            log.info("Starting device channel update: deviceId={}", deviceId);
            updateDeviceChannels(deviceId, profiles);
            log.info("Device channel update completed: deviceId={}", deviceId);
        } catch (Exception e) {
            long channelUpdateTime = System.currentTimeMillis() - channelUpdateStartTime;
            long totalTime = System.currentTimeMillis() - refreshStartTime;
            
            log.error("=== Device Channel Refresh Exception Diagnosis ===");
            log.error("Device: {}:{} ({})", device.getIpAddress(), device.getPort(), device.getName());
            log.error("Exception occurred during channel update phase, duration: {}ms", channelUpdateTime);
            log.error("Total duration: {}ms", totalTime);
            log.error("Exception type: {}", e.getClass().getSimpleName());
            log.error("Exception message: {}", e.getMessage());
            
            // 分析异常原因
            String errorAnalysis = analyzeChannelUpdateError(e);
            log.error("Exception analysis: {}", errorAnalysis);
            
            log.error("Profile information: Total={}, Valid RTSP={}", profiles.size(), validRtspCount);
            
            throw new RuntimeException("Failed to update device channels: " + errorAnalysis, e);
        }
        
        long channelUpdateTime = System.currentTimeMillis() - channelUpdateStartTime;
        log.info("Channel update completed, duration: {}ms", channelUpdateTime);
        
        // 修复：使用字符串deviceId查询通道，确保查询正确的设备
        List<OnvifChannel> channels = getChannelsByDeviceIdString(deviceId);
        log.info("Retrieved {} channels after update using deviceId: {}", channels.size(), deviceId);
        
        // 如果仍然没有通道，尝试直接从数据库查询验证
        if (channels.isEmpty()) {
            log.warn("No channels found using deviceId, attempting direct database verification");
            OnvifDevice verifyDevice = deviceRepository.findByDeviceId(deviceId).orElse(null);
            if (verifyDevice != null) {
                List<OnvifChannel> directChannels = channelRepository.findByDevice(verifyDevice);
                log.info("Direct database query found {} channels", directChannels.size());
                channels = directChannels;
            }
        }
        
        long totalTime = System.currentTimeMillis() - refreshStartTime;
        
        log.info("=== Device Channel Refresh Diagnosis Completed ===");
        log.info("Device: {}:{} ({})", device.getIpAddress(), device.getPort(), device.getName());
        log.info("Total refresh duration: {}ms", totalTime);
        log.info("Final channel count: {}", channels.size());
        log.info("Profile count: {}", profiles.size());
        log.info("Valid RTSP count: {}", validRtspCount);
        log.info("Channel creation success rate: {}%", profiles.size() > 0 ? (channels.size() * 100 / profiles.size()) : 0);
        
        // 时间分析
        log.info("Time analysis:");
        log.info("- Profile retrieval: {}ms ({}%)", profilesTime, totalTime > 0 ? (profilesTime * 100 / totalTime) : 0);
        log.info("- Channel update: {}ms ({}%)", channelUpdateTime, totalTime > 0 ? (channelUpdateTime * 100 / totalTime) : 0);
        
        // 记录每个通道的基本信息
        log.info("Channel details:");
        int enabledCount = 0;
        for (int i = 0; i < channels.size(); i++) {
            OnvifChannel channel = channels.get(i);
            if (channel.getEnabled()) enabledCount++;
            log.info("Channel {}: id={}, name={}, token={}, enabled={}, RTSP={}", 
                i + 1, channel.getId(), channel.getName(), channel.getProfileToken(), 
                channel.getEnabled() ? "✓" : "✗",
                channel.getRtspUrl() != null && !channel.getRtspUrl().trim().isEmpty() ? "✓" : "✗");
        }
        
        log.info("Channel status statistics: Total={}, Enabled={}, Enable rate={}%", 
            channels.size(), enabledCount, 
            channels.size() > 0 ? (enabledCount * 100 / channels.size()) : 0);
        
        if (channels.size() < profiles.size()) {
            log.warn("Some profiles failed to create channels, please check profile quality and RTSP URL validity");
        }
        
        return channels;
    }
    
    /**
     * 分析Profile获取错误
     */
    private String analyzeProfileError(Exception e) {
        if (e.getMessage() == null) {
            return "Failed to refresh device channels: Unknown error";
        }
        
        String message = e.getMessage().toLowerCase();
        
        if (message.contains("媒体服务") || message.contains("media service")) {
            return "Device does not support media service or failed to get media service address, please check device ONVIF configuration";
        } else if (message.contains("超时") || message.contains("timeout")) {
            return "Device response timeout, please check network connection and device load";
        } else if (message.contains("401") || message.contains("unauthorized")) {
            return "Device authentication failed, please check username and password";
        } else if (message.contains("404") || message.contains("not found")) {
            return "Device service path does not exist, please check ONVIF service configuration";
        } else if (message.contains("连接") || message.contains("connection")) {
            return "Unable to connect to device, please check device network status and firewall settings";
        } else if (message.contains("soap") || message.contains("xml")) {
            return "Device returned malformed SOAP response, possibly a device firmware issue";
        } else if (message.contains("profile")) {
            return "Device Profile parsing failed, possibly a device compatibility issue";
        } else {
            return "Failed to refresh device channels: " + e.getMessage();
        }
    }
    
    /**
     * 分析通道更新错误
     */
    private String analyzeChannelUpdateError(Exception e) {
        if (e.getMessage() == null) {
            return "Channel update failed: Unknown error";
        }
        
        String message = e.getMessage().toLowerCase();
        
        if (message.contains("数据库") || message.contains("database") || message.contains("sql")) {
            return "Database operation failed, possibly database connection issues or data constraint conflicts";
        } else if (message.contains("事务") || message.contains("transaction")) {
            return "Database transaction failed, possibly concurrent operation conflicts";
        } else if (message.contains("重复") || message.contains("duplicate") || message.contains("unique")) {
            return "Channel data duplication, possibly duplicate profile tokens or channel name conflicts";
        } else if (message.contains("空") || message.contains("null") || message.contains("empty")) {
            return "Channel data incomplete, possibly missing profile information";
        } else if (message.contains("长度") || message.contains("length") || message.contains("too long")) {
            return "Channel data length exceeded, possibly RTSP URL or channel name too long";
        } else if (message.contains("格式") || message.contains("format") || message.contains("invalid")) {
            return "Channel data format error, possibly incorrect RTSP URL format";
        } else if (message.contains("权限") || message.contains("permission") || message.contains("access")) {
            return "Insufficient database access permissions";
        } else if (message.contains("连接") || message.contains("connection")) {
            return "Database connection failed, please check database service status";
        } else {
            return "Channel update failed: " + e.getMessage();
        }
    }
    
    /**
     * 检测设备类型
     */
    private String detectDeviceType(OnvifDevice device) {
        if (device == null) {
            return null;
        }
        
        // 优先根据制造商信息判断
        if (device.getManufacturer() != null) {
            String manufacturer = device.getManufacturer().toLowerCase();
            if (manufacturer.contains("hikvision") || manufacturer.contains("hik") || manufacturer.contains("海康")) {
                return "hikvision";
            } else if (manufacturer.contains("dahua") || manufacturer.contains("dh") || manufacturer.contains("大华")) {
                return "dahua";
            } else if (manufacturer.contains("uniview") || manufacturer.contains("uni") || manufacturer.contains("宇视")) {
                return "uniview";
            } else if (manufacturer.contains("axis")) {
                return "axis";
            } else if (manufacturer.contains("bosch")) {
                return "bosch";
            } else if (manufacturer.contains("sony")) {
                return "sony";
            }
        }
        
        // 根据设备名称判断
        if (device.getName() != null) {
            String name = device.getName().toLowerCase();
            if (name.contains("hikvision") || name.contains("hik") || name.contains("ds-")) {
                return "hikvision";
            } else if (name.contains("dahua") || name.contains("dh")) {
                return "dahua";
            } else if (name.contains("uniview") || name.contains("uni")) {
                return "uniview";
            }
        }
        
        // 根据设备型号判断
        if (device.getModel() != null) {
            String model = device.getModel().toLowerCase();
            if (model.contains("ds-") || model.contains("hikvision")) {
                return "hikvision";
            } else if (model.contains("dh-") || model.contains("dahua")) {
                return "dahua";
            } else if (model.contains("ipc") && model.contains("uni")) {
                return "uniview";
            }
        }
        
        // 根据服务URL判断
        if (device.getServiceUrl() != null) {
            String url = device.getServiceUrl().toLowerCase();
            if (url.contains("hikvision") || url.contains("hik") || 
                url.contains("/onvif/device_service") || url.contains("/onvif/media_service")) {
                return "hikvision";
            } else if (url.contains("dahua") || url.contains("dh")) {
                return "dahua";
            }
        }
        
        return null; // 未知设备类型
    }
    
    /**
     * 判断是否为海康威视设备（保持向后兼容）
     */
    private boolean isHikvisionDevice(OnvifDevice device) {
        return "hikvision".equals(detectDeviceType(device));
    }
    
    /**
     * 记录认证策略选择过程
     */
    private void logAuthenticationStrategy(OnvifDevice device, String deviceType) {
        log.info("--- Authentication Strategy Analysis ---");
        log.info("Device type: {}", deviceType != null ? deviceType.toUpperCase() : "Generic device");
        
        if ("hikvision".equals(deviceType)) {
            log.info("Hikvision device authentication strategy priority:");
            log.info("1. HikvisionDigest authentication (Hikvision-specific Digest authentication)");
            log.info("   - Optimized Digest algorithm specifically for Hikvision devices");
            log.info("   - Supports Hikvision-specific authentication headers and parameters");
            log.info("2. Basic authentication (HTTP Basic authentication)");
            log.info("   - Standard HTTP Basic authentication");
            log.info("3. Standard Digest authentication (Generic Digest authentication)");
            log.info("   - RFC 2617 standard Digest authentication");
            log.info("4. No authentication (last attempt)");
        } else if ("dahua".equals(deviceType)) {
            log.info("Dahua device authentication strategy priority:");
            log.info("1. Basic authentication (HTTP Basic authentication)");
            log.info("   - Dahua devices typically prioritize Basic authentication support");
            log.info("2. Standard Digest authentication (Generic Digest authentication)");
            log.info("   - RFC 2617 standard Digest authentication");
            log.info("3. No authentication (last attempt)");
        } else if ("uniview".equals(deviceType)) {
            log.info("Uniview device authentication strategy priority:");
            log.info("1. Basic authentication (HTTP Basic authentication)");
            log.info("2. Standard Digest authentication (Generic Digest authentication)");
            log.info("3. No authentication (last attempt)");
        } else {
            log.info("Generic device authentication strategy priority:");
            log.info("1. Basic authentication (HTTP Basic authentication)");
            log.info("   - Most commonly used HTTP authentication method");
            log.info("2. Standard Digest authentication (Generic Digest authentication)");
            log.info("   - RFC 2617 standard Digest authentication");
            log.info("3. No authentication (last attempt)");
        }
        
        log.info("Authentication info: Username={}, Password={}", 
            device.getUsername(), device.getPassword() != null ? "[Set]" : "[Not set]");
    }
    
    /**
     * 分析可能的认证方式
     */
    private void analyzeAuthenticationMethods(OnvifDevice device, String deviceType) {
        log.info("--- Authentication Method Analysis ---");
        
        // 分析用户名密码强度
        if (device.getUsername() != null && device.getPassword() != null) {
            log.info("Username analysis: Length={}, Type={}", 
                device.getUsername().length(),
                device.getUsername().equals("admin") ? "Default admin" : "Custom username");
            
            int passwordLength = device.getPassword().length();
            String passwordStrength = "Unknown";
            if (passwordLength < 6) {
                passwordStrength = "Weak";
            } else if (passwordLength < 12) {
                passwordStrength = "Medium";
            } else {
                passwordStrength = "Strong";
            }
            log.info("Password analysis: Length={}, Strength={}", passwordLength, passwordStrength);
        }
        
        // 根据设备类型给出认证建议
        if ("hikvision".equals(deviceType)) {
            log.info("Hikvision device authentication recommendations:");
            log.info("- Prioritize HikvisionDigest authentication for best compatibility");
            log.info("- If HikvisionDigest fails, try Basic authentication");
            log.info("- Ensure username and password match device web interface login credentials");
            log.info("- Hikvision devices typically support default accounts like admin/12345");
        } else if ("dahua".equals(deviceType)) {
            log.info("Dahua device authentication recommendations:");
            log.info("- Prioritize Basic authentication, Dahua devices have good Basic authentication compatibility");
            log.info("- Dahua devices typically support default accounts like admin/admin");
            log.info("- Note that Dahua devices may have password complexity requirements");
        } else {
            log.info("Generic device authentication recommendations:");
            log.info("- Prioritize Basic authentication for widest compatibility");
            log.info("- If Basic fails, try Digest authentication");
            log.info("- Ensure device ONVIF service is enabled");
        }
    }
    
    /**
     * 记录连接成功的认证方式
     */
    private void logSuccessfulAuthentication(OnvifDevice device, int retryCount, long connectionTime) {
        log.info("--- Connection Success Analysis ---");
        log.info("Device: {}:{}", device.getIpAddress(), device.getPort());
        log.info("Retry count: {}", retryCount);
        log.info("Connection duration: {}ms", connectionTime);
        
        if (connectionTime < 1000) {
            log.info("Connection speed: Fast (<1 second)");
        } else if (connectionTime < 3000) {
            log.info("Connection speed: Normal (1-3 seconds)");
        } else {
            log.info("Connection speed: Slow (>3 seconds)");
        }
        
        if (retryCount == 1) {
            log.info("Connection stability: Excellent (first connection successful)");
        } else if (retryCount <= 2) {
            log.info("Connection stability: Good (few retries)");
        } else {
            log.info("Connection stability: Average (multiple retries)");
        }
    }
    
    /**
     * Analyze connection errors
     */
    private String analyzeConnectionError(Exception e) {
        if (e.getMessage() == null) {
            return "Unknown connection error";
        }
        
        String message = e.getMessage().toLowerCase();
        
        if (message.contains("timeout") || message.contains("sockettimeoutexception")) {
            return "Network timeout - Check network connection and device response speed";
        } else if (message.contains("connection refused") || message.contains("connectexception")) {
            return "Connection refused - Check device IP, port and ONVIF service status";
        } else if (message.contains("unknown host") || message.contains("unknownhostexception")) {
            return "Cannot resolve host - Check if IP address is correct";
        } else if (message.contains("connection reset")) {
            return "Connection reset - Possible network instability or high device load";
        } else if (message.contains("unexpected end of file")) {
            return "Connection unexpectedly closed - Possible device restart or network interruption";
        } else if (message.contains("401") || message.contains("unauthorized")) {
            return "Authentication failed - Check username, password and device authentication configuration";
        } else if (message.contains("404") || message.contains("not found")) {
            return "Service not found - Check ONVIF service address and device ONVIF support";
        } else if (message.contains("403") || message.contains("forbidden")) {
            return "Access forbidden - Check user permissions and device security settings";
        } else if (message.contains("500") || message.contains("internal server error")) {
            return "Device internal error - Check device status or restart device";
        } else {
            return "Connection exception: " + e.getMessage();
        }
    }
    
    /**
     * Update channel
     * 
     * @param id Channel ID
     * @param channel Channel information
     * @return Updated channel
     */
    @Transactional
    public OnvifChannel updateChannel(Long id, OnvifChannel channel) {
        OnvifChannel existingChannel = channelRepository.findById(id)
            .orElseThrow(() -> new RuntimeException("Channel not found: " + id));
        
        // Update channel information
        existingChannel.setName(channel.getName());
        existingChannel.setEnabled(channel.getEnabled());
        
        return channelRepository.save(existingChannel);
    }

    /**
     * Delete channel
     * 
     * @param id Channel ID
     */
    @Transactional
    public void deleteChannel(Long id) {
        log.info("Deleting ONVIF channel: {}", id);
        
        OnvifChannel channel = channelRepository.findById(id)
            .orElseThrow(() -> new RuntimeException("Channel not found: " + id));
        
        channelRepository.delete(channel);
    }

    // ========== Channel configuration related methods ==========

    /**
     * Get channel configuration
     * 
     * @param id Channel ID
     * @return Channel configuration
     */
    public Map<String, Object> getChannelConfig(Long id) {
        OnvifChannel channel = channelRepository.findById(id)
            .orElseThrow(() -> new RuntimeException("Channel not found: " + id));
        
        Map<String, Object> config = new HashMap<>();
        config.put("channelId", channel.getId());
        config.put("name", channel.getName());
        config.put("enabled", channel.getEnabled());
        config.put("profileToken", channel.getProfileToken());
        config.put("streamUri", channel.getRtspUrl());
        config.put("status", channel.getStatus());
        
        // Get detailed configuration from ONVIF device
        try {
            Map<String, Object> onvifConfig = onvifClientService.getChannelConfiguration(channel.getDevice(), channel.getProfileToken());
            config.putAll(onvifConfig);
        } catch (Exception e) {
            log.warn("Failed to get ONVIF channel configuration: {}", e.getMessage());
        }
        
        return config;
    }

    /**
     * Update channel configuration
     * 
     * @param id Channel ID
     * @param config Channel configuration
     * @return Updated configuration
     */
    @Transactional
    public Map<String, Object> updateChannelConfig(Long id, Map<String, Object> config) {
        OnvifChannel channel = channelRepository.findById(id)
            .orElseThrow(() -> new RuntimeException("Channel not found: " + id));
        
        // Update basic information
        if (config.containsKey("name")) {
            channel.setName((String) config.get("name"));
        }
        if (config.containsKey("enabled")) {
            channel.setEnabled((Boolean) config.get("enabled"));
        }
        
        channelRepository.save(channel);
        
        // Update ONVIF device configuration
        try {
            onvifClientService.updateChannelConfiguration(channel.getDevice(), channel.getProfileToken(), config);
        } catch (Exception e) {
            log.warn("Failed to update ONVIF channel configuration: {}", e.getMessage());
        }
        
        return getChannelConfig(id);
    }

    // ========== Preset related methods ==========

    /**
     * Get channel preset list
     * 
     * @param id Channel ID
     * @return Preset list
     */
    public List<Map<String, Object>> getChannelPresets(Long id) {
        OnvifChannel channel = channelRepository.findById(id)
            .orElseThrow(() -> new RuntimeException("Channel not found: " + id));
        
        try {
            return onvifClientService.getPresets(channel.getDevice(), channel.getProfileToken());
        } catch (Exception e) {
            log.error("Failed to get preset list: {}", e.getMessage());
            throw new RuntimeException("Failed to get preset list: " + e.getMessage());
        }
    }

    /**
     * Set channel preset
     * 
     * @param id Channel ID
     * @param preset Preset information
     * @return Set result
     */
    public Map<String, Object> setChannelPreset(Long id, Map<String, Object> preset) {
        OnvifChannel channel = channelRepository.findById(id)
            .orElseThrow(() -> new RuntimeException("Channel not found: " + id));
        
        try {
            return onvifClientService.setPreset(channel.getDevice(), channel.getProfileToken(), preset);
        } catch (Exception e) {
            log.error("Failed to set preset: {}", e.getMessage());
            throw new RuntimeException("Failed to set preset: " + e.getMessage());
        }
    }

    /**
     * Go to channel preset
     * 
     * @param id Channel ID
     * @param presetToken Preset token
     * @return Go to result
     */
    public Map<String, Object> gotoChannelPreset(Long id, String presetToken) {
        OnvifChannel channel = channelRepository.findById(id)
            .orElseThrow(() -> new RuntimeException("Channel not found: " + id));
        
        try {
            return onvifClientService.gotoPreset(channel.getDevice(), channel.getProfileToken(), presetToken);
        } catch (Exception e) {
            log.error("Failed to go to preset: {}", e.getMessage());
            throw new RuntimeException("Failed to go to preset: " + e.getMessage());
        }
    }

    /**
     * Remove channel preset
     * 
     * @param id Channel ID
     * @param presetToken Preset token
     */
    public void removeChannelPreset(Long id, String presetToken) {
        OnvifChannel channel = channelRepository.findById(id)
            .orElseThrow(() -> new RuntimeException("Channel not found: " + id));
        
        try {
            onvifClientService.removePreset(channel.getDevice(), channel.getProfileToken(), presetToken);
        } catch (Exception e) {
            log.error("Failed to remove preset: {}", e.getMessage());
            throw new RuntimeException("Failed to remove preset: " + e.getMessage());
        }
    }

    // ========== PTZ control related methods ==========

    /**
     * PTZ control
     * 
     * @param id Channel ID
     * @param command PTZ command
     * @return Control result
     */
    public Map<String, Object> ptzControl(Long id, Map<String, Object> command) {
        OnvifChannel channel = channelRepository.findById(id)
            .orElseThrow(() -> new RuntimeException("Channel not found: " + id));
        
        try {
            return onvifClientService.ptzControl(channel.getDevice(), channel.getProfileToken(), command);
        } catch (Exception e) {
            log.error("PTZ control failed: {}", e.getMessage());
            throw new RuntimeException("PTZ control failed: " + e.getMessage());
        }
    }

    // ========== Recording related methods ==========

    /**
     * Get channel recording list
     * 
     * @param id Channel ID
     * @param startTime Start time
     * @param endTime End time
     * @param page Page number
     * @param size Page size
     * @return Recording list
     */
    public Map<String, Object> getChannelRecordings(Long id, String startTime, String endTime, int page, int size) {
        OnvifChannel channel = channelRepository.findById(id)
            .orElseThrow(() -> new RuntimeException("Channel not found: " + id));
        
        try {
            return onvifClientService.getRecordings(channel.getDevice(), channel.getProfileToken(), startTime, endTime, page, size);
        } catch (Exception e) {
            log.error("Failed to get recording list: {}", e.getMessage());
            throw new RuntimeException("Failed to get recording list: " + e.getMessage());
        }
    }

    /**
     * Start recording
     * 
     * @param id Channel ID
     * @param config Recording configuration
     * @return Recording result
     */
    public Map<String, Object> startRecording(Long id, Map<String, Object> config) {
        OnvifChannel channel = channelRepository.findById(id)
            .orElseThrow(() -> new RuntimeException("Channel not found: " + id));
        
        try {
            return onvifClientService.startRecording(channel.getDevice(), channel.getProfileToken(), config);
        } catch (Exception e) {
            log.error("Failed to start recording: {}", e.getMessage());
            throw new RuntimeException("Failed to start recording: " + e.getMessage());
        }
    }

    /**
     * Stop recording
     * 
     * @param id Channel ID
     * @return Stop result
     */
    public Map<String, Object> stopRecording(Long id) {
        OnvifChannel channel = channelRepository.findById(id)
            .orElseThrow(() -> new RuntimeException("Channel not found: " + id));
        
        try {
            return onvifClientService.stopRecording(channel.getDevice(), channel.getProfileToken());
        } catch (Exception e) {
            log.error("Failed to stop recording: {}", e.getMessage());
            throw new RuntimeException("Failed to stop recording: " + e.getMessage());
        }
    }

    /**
     * Download recording
     * 
     * @param id Channel ID
     * @param recordingId Recording ID
     * @return Download response
     */
    public ResponseEntity<byte[]> downloadRecording(Long id, String recordingId) {
        OnvifChannel channel = channelRepository.findById(id)
            .orElseThrow(() -> new RuntimeException("Channel not found: " + id));
        
        try {
            return onvifClientService.downloadRecording(channel.getDevice(), recordingId);
        } catch (Exception e) {
            log.error("Failed to download recording: {}", e.getMessage());
            throw new RuntimeException("Failed to download recording: " + e.getMessage());
        }
    }

    /**
     * Delete recording
     * 
     * @param id Channel ID
     * @param recordingId Recording ID
     */
    public void deleteRecording(Long id, String recordingId) {
        OnvifChannel channel = channelRepository.findById(id)
            .orElseThrow(() -> new RuntimeException("Channel not found: " + id));
        
        try {
            onvifClientService.deleteRecording(channel.getDevice(), recordingId);
        } catch (Exception e) {
            log.error("Failed to delete recording: {}", e.getMessage());
            throw new RuntimeException("Failed to delete recording: " + e.getMessage());
        }
    }

    // ========== Event related methods ==========

    /**
     * Get channel event list
     * 
     * @param id Channel ID
     * @param page Page number
     * @param size Page size
     * @return Event list
     */
    public Map<String, Object> getChannelEvents(Long id, int page, int size) {
        OnvifChannel channel = channelRepository.findById(id)
            .orElseThrow(() -> new RuntimeException("Channel not found: " + id));
        
        try {
            return onvifClientService.getEvents(channel.getDevice(), channel.getProfileToken(), page, size);
        } catch (Exception e) {
            log.error("Failed to get event list: {}", e.getMessage());
            throw new RuntimeException("Failed to get event list: " + e.getMessage());
        }
    }

    /**
     * Subscribe to channel events
     * 
     * @param id Channel ID
     * @param subscription Subscription configuration
     * @return Subscription result
     */
    public Map<String, Object> subscribeChannelEvents(Long id, Map<String, Object> subscription) {
        OnvifChannel channel = channelRepository.findById(id)
            .orElseThrow(() -> new RuntimeException("Channel not found: " + id));
        
        try {
            return onvifClientService.subscribeEvents(channel.getDevice(), channel.getProfileToken(), subscription);
        } catch (Exception e) {
            log.error("Failed to subscribe to events: {}", e.getMessage());
            throw new RuntimeException("Failed to subscribe to events: " + e.getMessage());
        }
    }

    /**
     * Unsubscribe from channel events
     * 
     * @param id Channel ID
     * @return Unsubscribe result
     */
    public Map<String, Object> unsubscribeChannelEvents(Long id) {
        OnvifChannel channel = channelRepository.findById(id)
            .orElseThrow(() -> new RuntimeException("Channel not found: " + id));
        
        try {
            return onvifClientService.unsubscribeEvents(channel.getDevice(), channel.getProfileToken());
        } catch (Exception e) {
            log.error("Failed to unsubscribe: {}", e.getMessage());
            throw new RuntimeException("Failed to unsubscribe: " + e.getMessage());
        }
    }

    // ========== Device extended functionality methods ==========

    /**
     * Sync device time
     * 
     * @param deviceId Device ID
     * @return Sync result
     */
    public Map<String, Object> syncDeviceTime(Long deviceId) {
        OnvifDevice device = deviceRepository.findById(deviceId)
            .orElseThrow(() -> new RuntimeException("Device not found: " + deviceId));
        
        return onvifClientService.syncDeviceTime(device);
    }

    /**
     * Get device network configuration
     * 
     * @param deviceId Device ID
     * @return Network configuration
     */
    public Map<String, Object> getDeviceNetworkConfig(Long deviceId) {
        OnvifDevice device = deviceRepository.findById(deviceId)
            .orElseThrow(() -> new RuntimeException("Device not found: " + deviceId));
        
        return onvifClientService.getDeviceNetworkConfig(device);
    }

    /**
     * Update device network configuration
     * 
     * @param deviceId 设备ID
     * @param config Network configuration
     * @return Update result
     */
    public Map<String, Object> updateDeviceNetworkConfig(Long deviceId, Map<String, Object> config) {
        OnvifDevice device = deviceRepository.findById(deviceId)
            .orElseThrow(() -> new RuntimeException("Device not found: " + deviceId));
        
        return onvifClientService.updateDeviceNetworkConfig(device, config);
    }

    /**
     * Restart device
     * 
     * @param deviceId 设备ID
     * @return Restart result
     */
    public Map<String, Object> rebootDevice(Long deviceId) {
        OnvifDevice device = deviceRepository.findById(deviceId)
            .orElseThrow(() -> new RuntimeException("Device not found: " + deviceId));
        
        return onvifClientService.rebootDevice(device);
    }

    /**
     * Get device capabilities
     * 
     * @param deviceId 设备ID
     * @return Device capabilities
     */
    public Map<String, Object> getDeviceCapabilities(Long deviceId) {
        OnvifDevice device = deviceRepository.findById(deviceId)
            .orElseThrow(() -> new RuntimeException("Device not found: " + deviceId));
        
        return onvifClientService.getDeviceCapabilities(device);
    }

    /**
     * Get device performance metrics
     * 
     * @param deviceId 设备ID
     * @param startTime Start time
     * @param endTime End time
     * @param interval Time interval
     * @return Performance metrics
     */
    public Map<String, Object> getDeviceMetrics(Long deviceId, String startTime, String endTime, String interval) {
        OnvifDevice device = deviceRepository.findById(deviceId)
            .orElseThrow(() -> new RuntimeException("Device not found: " + deviceId));
        
        return onvifClientService.getDeviceMetrics(device, startTime, endTime, interval);
    }

    // ========== Batch operation methods ==========

    /**
     * Batch operate channels
     * 
     * @param data Batch operation data
     * @return Operation result
     */
    @Transactional
    public Map<String, Object> batchOperateChannels(Map<String, Object> data) {
        String operation = (String) data.get("operation");
        @SuppressWarnings("unchecked")
        List<Long> channelIds = (List<Long>) data.get("channelIds");
        
        if (channelIds == null || channelIds.isEmpty()) {
            throw new RuntimeException("Channel ID list cannot be empty");
        }
        
        Map<String, Object> result = new HashMap<>();
        List<Map<String, Object>> successList = new ArrayList<>();
        List<Map<String, Object>> failureList = new ArrayList<>();
        
        for (Long channelId : channelIds) {
            try {
                switch (operation) {
                    case "enable":
                        toggleChannelEnabled(channelId, true);
                        successList.add(Map.of("channelId", channelId, "message", "Enabled successfully"));
                        break;
                    case "disable":
                        toggleChannelEnabled(channelId, false);
                        successList.add(Map.of("channelId", channelId, "message", "Disabled successfully"));
                        break;
                    case "delete":
                        deleteChannel(channelId);
                        successList.add(Map.of("channelId", channelId, "message", "Deleted successfully"));
                        break;
                    case "refresh":
                        OnvifChannel channel = channelRepository.findById(channelId).orElse(null);
                        if (channel != null) {
                            refreshChannelsByDevice(String.valueOf(channel.getDevice().getId()));
                            successList.add(Map.of("channelId", channelId, "message", "Refreshed successfully"));
                        } else {
                            failureList.add(Map.of("channelId", channelId, "message", "Channel not found"));
                        }
                        break;
                    default:
                        failureList.add(Map.of("channelId", channelId, "message", "Unsupported operation: " + operation));
                }
            } catch (Exception e) {
                failureList.add(Map.of("channelId", channelId, "message", "Operation failed: " + e.getMessage()));
            }
        }
        
        result.put("operation", operation);
        result.put("total", channelIds.size());
        result.put("success", successList.size());
        result.put("failure", failureList.size());
        result.put("successList", successList);
        result.put("failureList", failureList);
        
        return result;
    }

    /**
     * Refresh device channels by device ID
     * 
     * @param deviceId Device ID string
     * @return 通道列表
     */
    @Transactional
    public List<OnvifChannel> refreshChannelsByDeviceId(String deviceId) {
        log.info("Starting to refresh device channels: deviceId={}", deviceId);
        
        OnvifDevice device = deviceRepository.findByDeviceId(deviceId)
            .orElseThrow(() -> new RuntimeException("Device not found: " + deviceId));
        
        log.info("Found device: {}:{}, name: {}", device.getIpAddress(), device.getPort(), device.getName());
        log.info("Device authentication info: username={}, password={}", 
            device.getUsername() != null ? device.getUsername() : "null", 
            device.getPassword() != null ? "[Set]" : "null");
        
        // Check authentication info
        if (device.getUsername() == null || device.getPassword() == null || 
            device.getUsername().trim().isEmpty() || device.getPassword().trim().isEmpty()) {
            log.error("Device authentication info missing: deviceId={}, username={}, password={}", 
                deviceId, device.getUsername(), device.getPassword() != null ? "[Set]" : "null");
            throw new RuntimeException("Device authentication information missing");
        }
        
        // Test device connection first
        log.info("Testing device connection: {}:{}", device.getIpAddress(), device.getPort());
        boolean isConnected = onvifClientService.testConnection(device);
        if (!isConnected) {
            log.error("Device connection test failed: {}:{}", device.getIpAddress(), device.getPort());
            throw new RuntimeException("Unable to connect to device, please check device network connection, IP address, port and authentication info");
        }
        log.info("Device connection test successful: {}:{}", device.getIpAddress(), device.getPort());
        
        // 获取设备通道
        try {
            List<OnvifClientService.ProfileInfo> profiles = onvifClientService.getProfiles(device);
            if (profiles != null && !profiles.isEmpty()) {
                log.info("Got {} profiles, starting to update channel info", profiles.size());
                updateDeviceChannels(device.getDeviceId(), profiles);
                log.info("Channel info update completed");
            } else {
                log.warn("No profiles obtained, device: {}:{}", device.getIpAddress(), device.getPort());
            }
        } catch (Exception e) {
            log.error("Exception occurred while getting device profiles: {}:{} - {}", device.getIpAddress(), device.getPort(), e.getMessage(), e);
            throw new RuntimeException("Failed to refresh device channels: " + e.getMessage(), e);
        }
        
        List<OnvifChannel> channels = getChannelsByDeviceId(device.getId());
        log.info("Refresh completed, device {} has {} channels", deviceId, channels.size());
        return channels;
    }

    /**
     * Generate unique device ID
     * 
     * @return Device ID
     */
    private String generateDeviceId() {
        String deviceId;
        do {
            deviceId = generateGB28181DeviceId();
        } while (deviceRepository.findByDeviceId(deviceId).isPresent());
        return deviceId;
    }

    /**
     * 生成符合国标GB28181规范的20位设备ID
     * 格式：行政区划代码(8位) + 行业编码(2位) + 设备类型编码(3位) + 设备序列号(7位)
     * 
     * @return 20位数字字符串
     */
    private String generateGB28181DeviceId() {
        // 设备序列号 - 7位随机数字
        String serialNumber = String.format("%07d", 
            new java.util.Random().nextInt(10000000));
        
        return administrativeCode + industryCode + deviceTypeCode + serialNumber;
    }

    // ========== Event management related methods ==========

    /**
     * Get device event list
     */
    public Map<String, Object> getDeviceEvents(Long deviceId, int page, int size, String eventType, String level, String startTime, String endTime) {
        Map<String, Object> result = new HashMap<>();
        try {
            // Get all channels of the device
            List<OnvifChannel> channels = channelRepository.findByDeviceId(deviceId);
            
            // Simulate event data (should actually be retrieved from database or event storage)
            List<Map<String, Object>> events = new ArrayList<>();
            for (OnvifChannel channel : channels) {
                // Generate some simulated events for each channel
                for (int i = 0; i < 5; i++) {
                    Map<String, Object> event = new HashMap<>();
                    event.put("id", "event_" + channel.getId() + "_" + i);
                    event.put("deviceId", deviceId);
                    event.put("channelId", channel.getId());
                    event.put("channelName", channel.getName());
                    event.put("type", eventType != null ? eventType : "motion_detection");
                    event.put("level", level != null ? level : "warning");
                    event.put("message", "Motion event detected");
                    event.put("timestamp", new java.util.Date());
                    event.put("acknowledged", false);
                    events.add(event);
                }
            }
            
            // Pagination processing
            int start = page * size;
            int end = Math.min(start + size, events.size());
            List<Map<String, Object>> pagedEvents = events.subList(start, end);
            
            result.put("content", pagedEvents);
            result.put("totalElements", events.size());
            result.put("totalPages", (events.size() + size - 1) / size);
            result.put("currentPage", page);
            result.put("size", size);
            
        } catch (Exception e) {
            log.error("Failed to get device events: {}", e.getMessage());
            throw new RuntimeException("Failed to get device events: " + e.getMessage());
        }
        return result;
    }

    /**
     * Get all event list
     */
    public Map<String, Object> getAllEvents(int page, int size, String eventType, String level, String startTime, String endTime) {
        Map<String, Object> result = new HashMap<>();
        try {
            // Get all devices
            List<OnvifDevice> devices = deviceRepository.findAll();
            List<Map<String, Object>> allEvents = new ArrayList<>();
            
            for (OnvifDevice device : devices) {
                Map<String, Object> deviceEvents = getDeviceEvents(device.getId(), 0, 100, eventType, level, startTime, endTime);
                @SuppressWarnings("unchecked")
                List<Map<String, Object>> events = (List<Map<String, Object>>) deviceEvents.get("content");
                allEvents.addAll(events);
            }
            
            // Pagination processing
            int start = page * size;
            int end = Math.min(start + size, allEvents.size());
            List<Map<String, Object>> pagedEvents = allEvents.subList(start, end);
            
            result.put("content", pagedEvents);
            result.put("totalElements", allEvents.size());
            result.put("totalPages", (allEvents.size() + size - 1) / size);
            result.put("currentPage", page);
            result.put("size", size);
            
        } catch (Exception e) {
            log.error("Failed to get all events: {}", e.getMessage());
            throw new RuntimeException("Failed to get all events: " + e.getMessage());
        }
        return result;
    }

    /**
     * Subscribe to device events
     */
    public Map<String, Object> subscribeDeviceEvents(Long deviceId, Map<String, Object> eventConfig) {
        Map<String, Object> result = new HashMap<>();
        try {
            OnvifDevice device = deviceRepository.findById(deviceId)
                .orElseThrow(() -> new RuntimeException("Device not found: " + deviceId));
            
            // Get all channels of the device
            List<OnvifChannel> channels = channelRepository.findByDeviceId(deviceId);
            
            for (OnvifChannel channel : channels) {
                // Subscribe to events for each channel
                Map<String, Object> channelResult = subscribeChannelEvents(channel.getId(), eventConfig);
                log.info("Channel {} event subscription result: {}", channel.getName(), channelResult);
            }
            
            result.put("success", true);
            result.put("message", "Device event subscription successful");
            result.put("deviceId", deviceId);
            result.put("subscriptionId", "sub_device_" + deviceId + "_" + System.currentTimeMillis());
            
        } catch (Exception e) {
            log.error("Failed to subscribe to device events: {}", e.getMessage());
            throw new RuntimeException("Failed to subscribe to device events: " + e.getMessage());
        }
        return result;
    }

    /**
     * Unsubscribe from device events
     */
    public Map<String, Object> unsubscribeDeviceEvent(Long deviceId, String subscriptionId) {
        Map<String, Object> result = new HashMap<>();
        try {
            OnvifDevice device = deviceRepository.findById(deviceId)
                .orElseThrow(() -> new RuntimeException("Device not found: " + deviceId));
            
            // Get all channels of the device
            List<OnvifChannel> channels = channelRepository.findByDeviceId(deviceId);
            
            for (OnvifChannel channel : channels) {
                // Unsubscribe from events for each channel
                Map<String, Object> channelResult = unsubscribeChannelEvents(channel.getId());
                log.info("Channel {} unsubscribe result: {}", channel.getName(), channelResult);
            }
            
            result.put("success", true);
            result.put("message", "Device event unsubscription successful");
            result.put("deviceId", deviceId);
            result.put("subscriptionId", subscriptionId);
            
        } catch (Exception e) {
            log.error("Failed to unsubscribe from device events: {}", e.getMessage());
            throw new RuntimeException("Failed to unsubscribe from device events: " + e.getMessage());
        }
        return result;
    }

    /**
     * Get device event subscription list
     */
    public List<Map<String, Object>> getDeviceEventSubscriptions(Long deviceId) {
        List<Map<String, Object>> subscriptions = new ArrayList<>();
        try {
            OnvifDevice device = deviceRepository.findById(deviceId)
                .orElseThrow(() -> new RuntimeException("Device not found: " + deviceId));
            
            // Simulate subscription data
            Map<String, Object> subscription = new HashMap<>();
            subscription.put("id", "sub_device_" + deviceId);
            subscription.put("deviceId", deviceId);
            subscription.put("deviceName", device.getName());
            subscription.put("eventTypes", java.util.Arrays.asList("motion_detection", "line_crossing", "intrusion_detection"));
            subscription.put("status", "active");
            subscription.put("createTime", new java.util.Date());
            subscriptions.add(subscription);
            
        } catch (Exception e) {
            log.error("Failed to get device event subscription list: {}", e.getMessage());
            throw new RuntimeException("Failed to get device event subscription list: " + e.getMessage());
        }
        return subscriptions;
    }

    /**
     * Acknowledge event
     */
    public Map<String, Object> acknowledgeEvent(String eventId) {
        Map<String, Object> result = new HashMap<>();
        try {
            // Simulate event acknowledgment
            result.put("success", true);
            result.put("message", "Event acknowledged successfully");
            result.put("eventId", eventId);
            result.put("acknowledgeTime", new java.util.Date());
            
            log.info("Event {} acknowledged", eventId);
            
        } catch (Exception e) {
            log.error("Failed to acknowledge event: {}", e.getMessage());
            throw new RuntimeException("Failed to acknowledge event: " + e.getMessage());
        }
        return result;
    }

    /**
     * Delete event
     */
    public Map<String, Object> deleteEvent(String eventId) {
        Map<String, Object> result = new HashMap<>();
        try {
            // Simulate event deletion
            result.put("success", true);
            result.put("message", "Event deleted successfully");
            result.put("eventId", eventId);
            result.put("deleteTime", new java.util.Date());
            
            log.info("Event {} deleted", eventId);
            
        } catch (Exception e) {
            log.error("Failed to delete event: {}", e.getMessage());
            throw new RuntimeException("Failed to delete event: " + e.getMessage());
        }
        return result;
    }

    /**
     * Set device event configuration
     */
    public Map<String, Object> setDeviceEventConfig(Long deviceId, Map<String, Object> config) {
        Map<String, Object> result = new HashMap<>();
        try {
            OnvifDevice device = deviceRepository.findById(deviceId)
                .orElseThrow(() -> new RuntimeException("Device not found: " + deviceId));
            
            // Simulate setting event configuration
            result.put("success", true);
            result.put("message", "Event configuration set successfully");
            result.put("deviceId", deviceId);
            result.put("config", config);
            
            log.info("Device {} event configuration updated: {}", device.getName(), config);
            
        } catch (Exception e) {
            log.error("Failed to set device event configuration: {}", e.getMessage());
            throw new RuntimeException("Failed to set device event configuration: " + e.getMessage());
        }
        return result;
    }

    /**
     * Get device event configuration
     */
    public Map<String, Object> getDeviceEventConfig(Long deviceId) {
        Map<String, Object> config = new HashMap<>();
        try {
            OnvifDevice device = deviceRepository.findById(deviceId)
                .orElseThrow(() -> new RuntimeException("Device not found: " + deviceId));
            
            // Simulate event configuration
            config.put("deviceId", deviceId);
            config.put("deviceName", device.getName());
            config.put("eventTypes", java.util.Arrays.asList(
                java.util.Map.of("type", "motion_detection", "enabled", true, "sensitivity", 80),
                java.util.Map.of("type", "line_crossing", "enabled", false, "sensitivity", 70),
                java.util.Map.of("type", "intrusion_detection", "enabled", true, "sensitivity", 90)
            ));
            config.put("notificationEnabled", true);
            config.put("recordingEnabled", true);
            
            return config;
        } catch (Exception e) {
            log.error("Failed to get channel configuration: {}", e.getMessage());
            return new HashMap<>();
        }
    }
    
    /**
     * Enhanced channel validation and optimization method
     */
    private List<OnvifChannel> validateAndOptimizeChannels(List<OnvifChannel> channels, OnvifDevice device) {
        if (channels == null || channels.isEmpty()) {
            log.warn("Channel list is empty, no optimization needed");
            return new ArrayList<>();
        }
        
        List<OnvifChannel> validChannels = new ArrayList<>();
        
        for (OnvifChannel channel : channels) {
            try {
                // 加强验证必要字段
                if (channel.getProfileToken() == null) {
                    log.warn("Channel {} has null profile token, skipping optimization", channel.getChannelNo());
                    continue;
                }
                
                String profileToken = channel.getProfileToken().trim();
                if (profileToken.isEmpty()) {
                    log.warn("Channel {} profile token is empty after trim, skipping optimization", channel.getChannelNo());
                    continue;
                }
                
                // 验证token长度
                if (profileToken.length() > 200) {
                    log.warn("Channel {} profile token too long ({}), truncating", 
                        channel.getChannelNo(), profileToken.length());
                    profileToken = profileToken.substring(0, 200);
                }
                
                channel.setProfileToken(profileToken);
                
                if (channel.getDevice() == null) {
                    log.warn("Channel {} has no device association, skipping optimization", channel.getChannelNo());
                    continue;
                }
                
                // 验证和修复RTSP地址
                if (isValidRtspUrl(channel.getRtspUrl())) {
                    log.debug("Channel {} RTSP URL is valid: {}", channel.getChannelNo(), 
                        channel.getRtspUrl().substring(0, Math.min(50, channel.getRtspUrl().length())) + "...");
                } else {
                    log.warn("Channel {} RTSP URL is invalid, attempting to fix: {}", 
                        channel.getChannelNo(), channel.getRtspUrl());
                    
                    String fixedUrl = validateAndEnhanceRtspUrl(channel.getRtspUrl(), device);
                    if (fixedUrl != null && isValidRtspUrl(fixedUrl)) {
                        channel.setRtspUrl(fixedUrl);
                        log.info("Channel {} RTSP URL fixed successfully", channel.getChannelNo());
                    } else {
                        log.warn("Channel {} RTSP URL cannot be fixed, keeping original", channel.getChannelNo());
                    }
                }
                
                // 设置默认值
                if (channel.getName() == null || channel.getName().trim().isEmpty()) {
                    channel.setName("通道" + channel.getChannelNo());
                }
                
                if (channel.getEnabled() == null) {
                    channel.setEnabled(true);
                }
                
                if (channel.getStatus() == null) {
                    channel.setStatus(OnvifChannel.ChannelStatus.ACTIVE);
                }
                
                validChannels.add(channel);
                log.debug("Channel {} validation and optimization completed", channel.getChannelNo());
                
            } catch (Exception e) {
                log.error("Channel {} optimization failed: {}", channel.getChannelNo(), e.getMessage(), e);
            }
        }
        
        log.info("Channel validation and optimization completed: input={}, valid={}, filtered={}", 
            channels.size(), validChannels.size(), channels.size() - validChannels.size());
        
        return validChannels;
    }
    
    /**
     * Validate RTSP URL validity
     */
    private boolean isValidRtspUrl(String rtspUrl) {
        if (StrUtil.isEmpty(rtspUrl)) {
            return false;
        }
        
        try {
            // Basic format check
            if (!rtspUrl.toLowerCase().startsWith("rtsp://")) {
                return false;
            }
            
            // Check if it contains necessary components
            if (!rtspUrl.contains("@") && !rtspUrl.matches(".*://[^/]+/.*")) {
                return false;
            }
            
            // Check port number (if exists)
            Pattern portPattern = Pattern.compile(":([0-9]+)/");
            Matcher matcher = portPattern.matcher(rtspUrl);
            if (matcher.find()) {
                int port = Integer.parseInt(matcher.group(1));
                if (port < 1 || port > 65535) {
                    return false;
                }
            }
            
            return true;
            
        } catch (Exception e) {
            log.debug("RTSP URL validation exception: {} - {}", rtspUrl, e.getMessage());
            return false;
        }
    }
    
    /**
     * Try to fix RTSP address
     */
    private String fixRtspUrl(String rtspUrl, OnvifDevice device) {
        if (StrUtil.isEmpty(rtspUrl) || device == null) {
            return null;
        }
        
        try {
            // Fix common issues
            String fixed = rtspUrl.trim();
            
            // Ensure it starts with rtsp://
            if (!fixed.toLowerCase().startsWith("rtsp://")) {
                if (fixed.startsWith("//")) {
                    fixed = "rtsp:" + fixed;
                } else {
                    fixed = "rtsp://" + fixed;
                }
            }
            
            // If authentication information is missing, try to add it
            if (!fixed.contains("@") && StrUtil.isNotEmpty(device.getUsername()) && StrUtil.isNotEmpty(device.getPassword())) {
                String auth = device.getUsername() + ":" + device.getPassword() + "@";
                fixed = fixed.replace("rtsp://", "rtsp://" + auth);
            }
            
            // Validate the fixed URL
            if (isValidRtspUrl(fixed)) {
                return fixed;
            }
            
        } catch (Exception e) {
            log.debug("RTSP URL fix failed: {} - {}", rtspUrl, e.getMessage());
        }
        
        return null;
    }
}